【问题标题】:Float and double datatype in JavaJava中的浮点和双精度数据类型
【发布时间】:2015-02-20 06:43:26
【问题描述】:

float 数据类型是单精度 32 位 IEEE 754 浮点数,double 数据类型是双精度 64 位 IEEE 754 浮点数。

这是什么意思?我什么时候应该使用 float 而不是 double 或反之亦然?

【问题讨论】:

  • 当内存使用很关键时,您应该使用浮点数而不是双精度数。如果您需要更精确的计算,请使用双精度数。
  • @Everv0id:我不确定在任何情况下内存如此紧张以至于不得不牺牲准确性来换取空间。 (您正在使用 Java,看在上帝的份上……)在某些情况下可能需要它,但在我的实践中,我很少看到它。如果您想详细说明为什么您认为这是一个好主意,那么提供一个带有 for-instance 的答案将是一个值得补充的内容。
  • @Makoto 实际上,我从来没有使用过花车,只有双打。但是可能有一些应用程序(理论上)应该保留大量的浮点数,因此 2 倍的内存使用可能是至关重要的。理论上,ofc;实际上,您总是可以购买另一台服务器
  • 我使用了 4 字节甚至 2 字节的固定精度数字来节省内存,但除非你有数十亿个这样的数字,否则不太值得。您写“double”而不是“float”(它多了一个字母)所花费的时间比您使用的额外内存价值多 1000 倍,但是如果使用 double 而不是 float 可以节省与精度相关的时间错误,值得。

标签: java floating-point double ieee-754


【解决方案1】:

上面的Wikipedia page 是一个很好的起点。

总结一下:

  • float 用 32 位表示,有 1 个符号位、8 个指数位和 23 个有效位(或从科学记数法数得出的数字:2.33728*1012;33728 是有效位)。

  • double 用 64 位表示,有 1 个符号位、11 位指数和 52 位有效数。

默认情况下,Java 使用double 来表示它的浮点数(所以文字3.14 被输入double)。它也是可以为您提供更大数字范围的数据类型,因此我强烈建议您在 float 上使用它。

可能有某些库实际上会强制您使用 float,但总的来说 - 除非您可以保证您的结果足够小以适合 floatprescribed range,否则最好选择double

如果您需要准确性 - 例如,您不能使用不准确的十进制值(例如 1/10 + 2/10),或者您正在使用货币进行任何操作(例如,代表 $10.33在系统中),然后使用BigDecimal,它可以支持任意数量的精度并优雅地处理此类情况。

【讨论】:

  • 在给定示例中不是 233728 == 尾数吗?我的意思是,整数部分还存储在哪里?
  • @mathguy54:在科学记数法中,2 是整数,0.33728 是尾数。 Here's a reference to that.
  • 我正在搜索浮点数和双精度数的信息,发现了这一点,需要评论:如果您使用不涉及小数美分的货币做任何事情,那么使用 BigDecimal 是荒谬的。通用货币是离散数据,因此您应该使用整数数据类型。 (这是年轻程序员最常犯的错误之一——因为我们使用 . 来区分美元和美分,他们认为这是一个浮点值。实际上不是。)
  • @TrixieWolf,您能否更具体一点,您是否建议使用两个整数(整数和小数部分)?你说的是通用货币,其余的呢?有些金额是用小数点 6 计算的,所以你不能简单地*100。拜托,你有一个观点,但你能更准确吗:)
  • @AxelH 除了可以存在小数美分的金融计算中间,货币总是离散的。您将使用一种整数类型来存储数据。所以 5.34 美元将存储为 534。美元部分在整数数学中是 val/100,美分在整数数学中是 val%100,其中 % 指的是余数运算。对于小数点后更多位的货币,它仍应存储为整数,因为它是离散的。即使它不是离散的,您通常也希望在大多数情况下退回到离散存储,因为它很精确,因此您不会因舍入错误而损失金钱。
【解决方案2】:

一个浮点数给你大约。 6-7 位小数精度,而双精度为您​​提供大约。 15-16。 double 的数字范围也更大。

double 需要 8 个字节的存储空间,而 float 只需要 4 个字节。

【讨论】:

    【解决方案3】:

    浮点数,也称为实数,用于计算需要小数精度的表达式。例如,诸如平方根之类的计算或诸如正弦和余弦之类的超越数会产生一个精度需要浮点类型的值。 Java 实现了标准 (IEEE–754) 浮点类型和运算符集。浮点类型有两种,float 和 double,分别代表单精度数和双精度数。它们的宽度和范围如下所示:


       Name     Width in Bits   Range 
        double  64              1 .7e–308 to 1.7e+308
        float   32              3 .4e–038 to 3.4e+038
    


    浮动

    float 类型指定使用 32 位存储的单精度值。单精度在某些处理器上速度更快,占用的空间是双精度的一半,但当值非常大或非常小时时会变得不精确。当您需要小数部分但不需要很高的精度时,浮点类型的变量很有用。

    以下是一些示例浮点变量声明:

    浮动高温,低温;


    双倍

    双精度,由 double 关键字表示,使用 64 位来存储一个值。在一些针对高速数学计算进行了优化的现代处理器上,双精度实际上比单精度更快。所有超越数学函数,例如 sin()、cos() 和 sqrt(),都返回双精度值。当您需要在多次迭代计算中保持准确性,或者正在处理大数值时,double 是最佳选择。

    【讨论】:

    • 这个答案清楚地阐明了我们何时应该使用 float 和 double。为什么不呢?
    • floatdouble 类型都不适合用于 Java 中的货币,因为它们为舍入错误提供了机会。本文更详细:javapractices.com/topic/TopicAction.do?Id=13
    • " float 在表示美元和美分时很有用。" - 不,不,不,非诺诺诺。永远不要将货币存储为浮点数/双精度数。
    【解决方案4】:

    这会报错:

    public class MyClass {
        public static void main(String args[]) {
            float a = 0.5;
        }
    }
    

    /MyClass.java:3: 错误:不兼容的类型:从双精度到浮点数的可能有损转换 浮动 a = 0.5;

    这会很好用

    public class MyClass {
        public static void main(String args[]) {
            double a = 0.5;
        }
    }
    

    这也可以很好地工作

    public class MyClass {
        public static void main(String args[]) {
            float a = (float)0.5;
        }
    }
    

    原因:默认情况下,Java 将实数存储为 double 以确保更高的精度。

    Double 占用更多空间但在计算过程中更精确,float 占用更少空间但不太精确。

    【讨论】:

      【解决方案5】:

      Java 似乎偏向于使用 double 进行计算:

      以我今天早些时候编写的程序为例,当我使用 float 时,这些方法不起作用,但现在当我用 double 替换 float 时效果很好(在 NetBeans IDE 中):

      package palettedos;
      import java.util.*;
      
      class Palettedos{
          private static Scanner Z = new Scanner(System.in);
          public static final double pi = 3.142;
      
          public static void main(String[]args){
              Palettedos A = new Palettedos();
              System.out.println("Enter the base and height of the triangle respectively");
              int base = Z.nextInt();
              int height = Z.nextInt();
              System.out.println("Enter the radius of the circle");
              int radius = Z.nextInt();
              System.out.println("Enter the length of the square");
              long length = Z.nextInt();
              double tArea = A.calculateArea(base, height);
              double cArea = A.calculateArea(radius);
              long sqArea = A.calculateArea(length);
              System.out.println("The area of the triangle is\t" + tArea);
              System.out.println("The area of the circle is\t" + cArea);
              System.out.println("The area of the square is\t" + sqArea);
          }
      
          double calculateArea(int base, int height){
              double triArea = 0.5*base*height;
              return triArea;
          }
      
          double calculateArea(int radius){
              double circArea = pi*radius*radius;
              return circArea;
          }
      
          long calculateArea(long length){
              long squaArea = length*length;
              return squaArea;
          }
      }
      

      【讨论】:

      • 我今天遇到了同样的问题。这种偏见背后的原因是什么?
      【解决方案6】:

      根据 IEEE 标准,float 是实数的 32 位表示,而 double 是 64 位表示。

      在 Java 程序中,我们通常会看到双精度数据类型的使用。这只是为了避免溢出,因为使用 double 数据类型可以容纳的数字范围大于使用 float 时的范围。

      此外,当需要高精度时,建议使用双精度。很少有很久以前实现的库方法仍然需要使用 float 数据类型作为必须的(那只是因为它是使用 float 实现的,没有别的!)。

      但是,如果您确定您的程序需要较小的数字并且使用 float 不会发生溢出,那么使用 float 将大大提高您的空间复杂度,因为 float 需要 double 所需的一半内存。

      【讨论】:

        【解决方案7】:

        这个例子说明了如何从 Java 中的浮点数中提取符号(最左边的位)、指数(后面的 8 位)和尾数(最右边的 23 位)。

        int bits = Float.floatToIntBits(-0.005f);
        int sign = bits >>> 31;
        int exp = (bits >>> 23 & ((1 << 8) - 1)) - ((1 << 7) - 1);
        int mantissa = bits & ((1 << 23) - 1);
        System.out.println(sign + " " + exp + " " + mantissa + " " +
          Float.intBitsToFloat((sign << 31) | (exp + ((1 << 7) - 1)) << 23 | mantissa));
        

        同样的方法可用于双精度数(11 位指数和 52 位尾数)。

        long bits = Double.doubleToLongBits(-0.005);
        long sign = bits >>> 63;
        long exp = (bits >>> 52 & ((1 << 11) - 1)) - ((1 << 10) - 1);
        long mantissa = bits & ((1L << 52) - 1);
        System.out.println(sign + " " + exp + " " + mantissa + " " +
          Double.longBitsToDouble((sign << 63) | (exp + ((1 << 10) - 1)) << 52 | mantissa));
        

        信用:http://s-j.github.io/java-float/

        【讨论】:

          【解决方案8】:

          您应该使用 double 而不是 float 来进行精确计算,而在使用不太精确的计算时应该使用 float 而不是 double。 Float 只包含十进制数,而 double 包含一个 IEEE754 双精度浮点数,更容易包含和计算更准确的数字。希望这会有所帮助。

          【讨论】:

            【解决方案9】:

            在常规编程计算中,我们不使用浮点数。如果我们确保结果范围在浮点数据类型的范围内,那么我们可以选择浮点数据类型来节省内存。通常,我们使用 double 有两个原因:-

            • 如果我们想使用浮点数作为浮点数据类型,那么方法调用者必须显式添加 F 或 f 后缀,因为默认情况下每个浮点数都被视为双精度数。增加了程序员的负担。如果我们使用浮点数作为双精度数据类型,那么我们不需要添加任何后缀。
            • Float 是单精度数据类型,占用 4 个字节。因此,在大型计算中,我们不会得到完整的结果。如果我们选择double数据类型,它占用8个字节,我们会得到完整的结果。

            float 和 double 数据类型都是专为科学计算而设计的,其中近似误差是可以接受的。如果准确性是最优先考虑的问题,则建议使用 BigDecimal 类而不是 float 或 double 数据类型。来源:-Float and double datatypes in Java

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-12-27
              • 2011-10-24
              • 1970-01-01
              • 2018-02-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-07-12
              相关资源
              最近更新 更多