比较 Java 中的 float 和 double 原语

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7392167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:45:35  来源:igfitidea点击:

Comparing float and double primitives in Java

javaoperatorsprimitive

提问by xyz

I came across a strange corner of Java.(It seems strange to me)

我遇到了Java的一个奇怪的角落。(对我来说似乎很奇怪)

double dd = 3.5;          
float ff = 3.5f;
System.out.println(dd==ff);   

o/p: true

o/p: 真的

double dd = 3.2;
float ff = 3.2f;
System.out.println(dd==ff);

o/p: false

o/p:错误

I observed that if we compare any two values (a float and a double as I mentioned in the example) with .5OR .0like 3.5, 234.5, 645.0 then output is truei.e. two values are equal otherwise output is falsethough they are equals.

我观察到,如果我们将任意两个值(我在示例中提到的浮点数和双精度数)与.5OR进行比较,例如.03.5、234.5、645.0,则输出true即两个值相等,否则输出false虽然它们相等。

Even I tried to make method strictfpbut no luck. Am I missing out on something.

即使我试图制定方法,strictfp但没有运气。我是不是错过了什么。

回答by Edwin Buck

Take a look at What every computer scientist should know about floating point numbers.

看看每个计算机科学家应该了解的关于浮点数的知识

Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation....

将无限多的实数压缩成有限数量的位需要一个近似表示......

--- Edit to show what the above quote means ---

--- 编辑以显示上述引用的含义---

You shouldn't ever compare floats or doubles for equality; because, you can't really guarantee that the number you assign to the float or double is exact.

你永远不应该比较浮点数或双数是否相等;因为,您不能真正保证分配给 float 或 double 的数字是准确的。

So

所以

 float x = 3.2f;

doesn't result in a float with a value of 3.2. It results in a float with a value of 3.2 plus or minus some very small error. Say 3.19999999997f. Now it should be obvious why the comparison won't work.

不会产生值为 3.2 的浮点数。它导致浮点数为 3.2 加上或减去一些非常小的误差。说 3.19999999997f。现在应该很明显为什么比较不起作用了。

To compare floats for equality sanely, you need to check if the value is "close enough" to the same value, like so

要合理地比较浮点数的相等性,您需要检查该值是否“足够接近”相同的值,就像这样

float error = 0.000001 * second;
if ((first >= second - error) || (first <= second + error)) {
   // close enough that we'll consider the two equal
   ...
}

回答by Jon Skeet

The difference is that 3.5 can be represented exactlyin both floatand double- whereas 3.2 can't be represented exactly in either type... and the two closest approximations are different.

不同之处在于 3.5 可以在两者中精确表示floatdouble而 3.2 不能在任何一种类型中精确表示......并且两个最接近的近似值是不同的。

Imagine we had two fixed-precision decimaltypes, one of which stored 4 significant digits and one of which stored 8 significant digits, and we asked each of them to store the number closest to "a third" (however we might do that). Then one would have the value 0.3333 and one would have the value 0.33333333.

假设我们有两种固定精度的十进制类型,一种存储 4 位有效数字,另一种存储 8 位有效数字,我们要求它们中的每一个存储最接近“三分之一”的数字(但是我们可能会这样做)。那么一个值为 0.3333,一个值为 0.33333333。

An equality comparison between floatand doublefirst converts the floatto a doubleand then compares the two - which would be equivalent to converting 0.3333 in our "small decimal" type to 0.33330000. It would then compare 0.33330000 and 0.33333333 for equality, and give a result of false.

float和之间的相等比较double首先将 转换float为 a double,然后比较两者 - 这相当于将我们的“小十进制”类型中的 0.3333 转换为 0.33330000。然后它将比较 0.33330000 和 0.33333333 是否相等,并给出 false 结果。

回答by Peter Lawrey

floating point is a binary format and it can represent numbers as a sum of powers of 2. e.g. 3.5 is 2 + 1 + 1/2.

浮点数是一种二进制格式,它可以将数字表示为 2 的幂之和。例如 3.5 是 2 + 1 + 1/2。

float 3.2f as an approximation of 3.2 is

float 3.2f 作为 3.2 的近似值是

2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/4194304 + a small error

However double 3.2d as an approximation of 3.2 is

然而双 3.2d 作为 3.2 的近似值是

2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/8388608+ 1/16777216+ 1/134217728+ 1/268435456+ 1/2147483648+ 1/4294967296+ 1/34359738368+ 1/68719476736+ 1/549755813888+ 1/1099511627776+ 1/8796093022208+ 1/17592186044416+ 1/140737488355328+ 1/281474976710656+ 1/1125899906842624 + a smaller error

When you use floating point, you need to use appropriate rounding. If you use BigDecimal instead (and many people do) it has rounding built in.

当您使用浮点数时,您需要使用适当的舍入。如果您改用 BigDecimal(很多人都这样做),它会内置四舍五入。

double dd = 3.2;          
float ff = 3.2f;
// compare the difference with the accuracy of float.
System.out.println(Math.abs(dd - ff) < 1e-7 * Math.abs(ff));


BTW the code I used to print the fractions for double.

顺便说一句,我用来打印双倍分数的代码。

double f = 3.2d;
double f2 = f - 3;
System.out.print("2+ 1");
for (long i = 2; i < 1L << 54; i <<= 1) {
  f2 *= 2;
  if (f2 >= 1) {
    System.out.print("+ 1/" + i);
    f2 -= 1;
  }
}
System.out.println();

回答by Kerrek SB

The common implementation of floating point numbers, IEEE754, allows for the precise representation of only those numbers which have a short, finite binary expansion, i.e. which are a sum of finitely many (nearby) powers of two. All other numbers cannot be precisely represented.

浮点数的通用实现 IEEE754 只允许精确表示那些具有短的、有限的二进制扩展的数字,即它们是 2 的有限多个(近似)幂的总和。所有其他数字都无法精确表示。

Since floatand doublehave different sizes, the representation in both types for a non-representable value are different, and thus they compare as unequal.

由于floatdouble具有不同的大小,因此不可表示值在两种类型中的表示是不同的,因此它们比较为不相等。

(The lengthof the binary string is the size of the mantissa, so that's 24 for float, 53 for doubleand 64 for the 80-bit extended-precision float (not in Java). The scaleis determined by the exponent.)

(二进制字符串的长度是尾数的大小,因此对于 80 位扩展精度浮点数是 24,对于float53double和 64(不是在 Java 中)。比例由指数决定。)

回答by Mike Argyriou

This should work:

这应该有效:

BigDecimal ddBD = new BigDecimal(""+dd);
BigDecimal ffBD = new BigDecimal(""+ff);

// test for equality
ddBO.equals(ffBD);

Always work with BigDecimalwhen you want to compare floats or doubles and always use the BigDecimal constructor with the String parameter!

与总是工作BigDecimal的时候要比较彩车或双打和经常使用的BigDecimal构造与字符串参数