http://www.gotw.ca/gotw/067.htm中有一个示例

int main()
{
  double x = 1e8;
  //float x = 1e8;
  while( x > 0 )
  {
    --x;
  }
}

当您将double更改为float时,在VS2008中这是一个无限循环。
根据Gotw的解释:



据我了解,IEEE754浮点数是单精度(32位),浮点数的范围应为+/- 3.4e +/- 38,并且有效位数应为7位数。

但是我仍然不明白这种情况是如何发生的:“最终达到无法表示的值N,并且对于该值N-1 == N(由于浮点精度不足)。”有人可以尝试解释一下吗?

一些额外的信息:当我使用double x = 1e8时,它在大约1秒内完成,当我将其更改为
float x = 1e8,它运行的时间更长(5分钟后仍在运行),如果我将其更改为float x = 1e7;,它也会在大约1秒钟内完成。

我的测试环境是VS2008。

顺便说一句,我是,而不是,因为我已经知道了,所以我要求基本的IEEE 754格式说明。

谢谢

最佳答案

好吧,为了便于讨论,假设我们有一个处理器,该处理器代表一个具有7个有效十进制数字的浮点数和一个具有2个十进制数字的尾数。所以现在数字1e8将存储为

1.000 000 e 08

(其中“。”和“e”实际上不需要存储。)

因此,现在您要计算“1e8-1”。 1表示为
1.000 000 e 00

现在,为了进行减法运算,我们首先以无限的精度进行减法运算,然后进行归一化处理,以使“。”之前的第一个数字生效。介于1到9之间,最后四舍五入到最接近的可表示值(例如,以偶数为盈亏)。 “1e8-1”的无限精度结果为
0.99 999 999 e 08

或归一化
9.9 999 999 e 07

可以看出,无限精度结果需要比我们的体系结构实际提供的位数多一位。因此,我们需要将无限精确的结果四舍五入(并重新规范化)为7个有效数字,结果是
1.000 000 e 08

因此,您最终得到“1e8-1 == 1e8”,并且循环永远不会终止。

现在,实际上您正在使用IEEE 754二进制浮点数,它们有点不同,但是原理大致相同。

关于c++ - Gotw 67中的示例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6995950/

10-11 10:49