由于浮点舍入错误,“floor”是否可能返回不准确的结果?

时间:2014-06-11 08:55:56

标签: c++ floating-point

我知道浮点数通常包括舍入误差。

当您取浮点(或双精度)的地板或天花板以将其转换为整数时,结果值是否准确或者可以" flo"价值仍然是近似值?

基本上,像floor(3.14159265)这样的东西是否有可能返回一个基本上为2.999999的值,当你试图将它转换为int时会转换为2?

3 个答案:

答案 0 :(得分:12)

  

地板(3.14159265)之类的东西是否有可能返回一个基本为2.999999的值?

floor()函数返回一个精确整数的浮点值。所以你的问题的前提是错误的。

现在,floor(x)返回不大于x的最接近的整数值。

总是如此
floor(x) <= x

且没有整数i,大于floor(x)i <= x

查看floor(3.14159265),这会返回3.0。对此没有争论。没什么好说的。

如果你感兴趣的话就是写floor(x),其中x是算术表达式的结果。浮点精度和舍入可能意味着x落在整数的错误一侧。换句话说,生成x的表达式的真值大于某个整数i,但使用浮点运算计算时x小于i

答案 1 :(得分:5)

小整数与浮点数完全相同,但大整数则不然。

但是,正如其他人指出的那样,浮点数无法表示的大整数永远不会被非整数表示,因此floor()永远不会返回非整数值。因此,只要它没有溢出,对(int)的强制转换就是正确的。

有多小?从这个answer

无耻地复制
  

对于float,它是16,777,217(2 24 + 1)。
  对于double,它是9,007,199,254,740,993(2 53 + 1)。

请注意,int(32位)的通常范围是2 31 ,因此float无法准确表示所有这些。如果需要,请使用double

答案 2 :(得分:5)

有趣的是,float可以精确地存储一定范围的整数,例如:

  • 1存储为尾数1(二进制1)*指数2 ^ 0
  • 2存储为尾数1(二进制1)*指数2 ^ 1
  • 3存储为尾数1.5(二进制1.1)*指数2 ^ 1
  • 4存储为尾数1 *指数2 ^ 2
  • 5存储为尾数1.25(二进制1.01)*指数2 ^ 2
  • 6存储为尾数1.5(二进制1.1)*指数2 ^ 2
  • 7存储为尾数1.75(二进制1.11)*指数2 ^ 2
  • 8存储为尾数1(二进制1)*指数2 ^ 3
  • 9存储为尾数1.125(二进制1.001)*指数2 ^ 3
  • 10存储为尾数1.25(二进制1.01)*指数2 ^ 3 ...

正如您所看到的,指数增加的方式可以使用尾数可以表示的完美存储的小数值。

通过将号码加入this great online conversion site,您可以很好地理解这一点。

一旦超过某个阈值,尾数中没有足够的数字来划分增加的指数的跨度而不先跳过每个奇数的整数值,然后是每四个中的三个,然后是8个中的7个等..对于超过此阈值的数字,问题不在于它们可能与整数值相差一些微小的分数量,它表示所有可表示的值都是整数而且不仅不能再表示小数部分,而是如上所述整数不可能是。

您可以在计算器中观察:

Binary                             Decimal
+-Exponent Mantissa
0 10010110 11111111111111111111111 16777215
0 10010111 00000000000000000000000 16777216
0 10010111 00000000000000000000001 16777218

看看在这个阶段,尾数的最小可能增量实际上是&#34;值得2&#34;以十进制值表示?

  

当您取浮点(或双精度)的地板或天花板以将其转换为整数时,结果值是否准确或者可以&#34; flo&#34;价值仍然是近似值?

总是准确的。楼层正在做的是有效地消除尾数中的任何一个,其重要性(它们对价值的贡献)无论如何都是分数。

  

基本上,像floor(3.14159265)这样的东西是否有可能返回一个基本上为2.999999的值,当你试图将它转换为int时会转换为2?

没有