0.1浮点数大于0.1的两倍。 我预料它是错误的

让:

double d = 0.1; float f = 0.1; 

应该expression

 (f > d) 

返回truefalse

经验上,答案是true 。 但是,我认为这是false

由于0.1不能完全以二进制表示,而double有1516位的精度,浮点数只有7 。 所以他们都小于0.1 ,而双倍更接近0.1

我需要一个确切的解释。

我想说的答案取决于舍入模式时,将double转换为floatfloat有24个二进制位的精度, double有53个。在二进制中,0.1是:

 0.1₁₀ = 0.0001100110011001100110011001100110011001100110011…₂ ^ ^ ^ ^ 1 10 20 24 

所以如果我们在第24位数字中取整,我们会得到

 0.1₁₀ ~ 0.000110011001100110011001101 

这大于53位的精确值和更精确的近似值。

数字0.1将被舍入到具有给定精度的最接近的浮点表示。 这个近似值可能大于或小于0.1,所以在不考虑实际值的情况下,无法预测单精度或双精度近似值是否更大。

这里是双精度值四舍五入(使用Python解释器):

 >>> "%.55f" % 0.1 '0.1000000000000000055511151231257827021181583404541015625' 

这里是单精度值:

 >>> "%.55f" % numpy.float32("0.1") '0.1000000014901161193847656250000000000000000000000000000' 

所以你可以看到单精度逼近更大。

如果你将.1转换为二进制,你会得到:

  0.000110011001100110011001100110011001100110011001100 ... 

永远重复

映射到数据types,你会得到:

 float(.1)=%.00011001100110011001101
                                      ^ ---注意四舍五入
双(.1)=%.0001100110011001100110011001100110011001100110011010

将其转换为10:

 float(.1)= .10000002384185791015625
 double(.1)= .100000000000000088817841970012523233890533447265625

这是从Bruce Dawson写的一篇文章中提取出来的。 它可以在这里find:
双打不是花车,所以不要比较它们

我认为Eric Lippert对这个问题的评论其实是最清楚的解释,所以我会把它作为答案重新发布:

假设你正在计算三位十进制和六位十进制的1/9。 0.111 <0.111111,对吗?

现在假设你正在计算6/9。 0.667> 0.666667,对吗?

三位十进制中的6/9不能是0.666,因为它不是最接近6/9的3位小数!

由于不能准确地表示,所以比较基数2的1/10就像比较基数10的1/7。

1/7 = 0.142857142857 …但是在不同的基准10精度(3对6位小数)进行比较时,我们有0.143> 0.142857。

只是添加其他答案,谈论IEEE-754和x86:这个问题比看起来更复杂。 在IEEE-754中没有“一”表示0.1,有两个。 将最后一位数字舍入或舍入将是有效的。 这种差异实际上可能发生 ,因为x86内部浮点计算使用64位; 它实际上使用80位! 这被称为双倍扩展精度 。

因此,即使是在x86编译器中,有时也会出现这样的情况:相同的数字表示两种不同的方式,因为有些使用64位计算二进制表示,而另一些则使用80。


事实上,甚至在同一台机器上,即使使用相同的编译器也可能发生这种情况!

 #include <iostream> #include <cmath> void foo(double x, double y) { if (std::cos(x) != std::cos(y)) { std::cout << "Huh?!?\n"; //← you might end up here when x == y!! } } int main() { foo(1.0, 1.0); return 0; } 

即使x == y为什么是cos(x) != cos(y) ? 获取更多信息。

在转换中,double的级别大于float。 通过做一个逻辑比较,f被转换为double,也许你正在使用的实现给出不一致的结果。 如果你后缀f,所以编译器将它注册为一个浮点数,那么你得到0.00,这是双重types的错误。 没有固定的浮动types是双倍的。

 #include <stdio.h> #include <float.h> int main() { double d = 0.1; float f = 0.1f; printf("%f\n", (f > d)); return 0; }