c – Gotw 67中的一个例子

c – Gotw 67中的一个例子,第1张

概述在 http://www.gotw.ca/gotw/067.htm有一个例子 int main(){ double x = 1e8; //float x = 1e8; while( x > 0 ) { --x; }} 当你将double改为float时,它在VS2008中是一个无限循环. 根据Gotw的解释: What if float can’t exactly 在 http://www.gotw.ca/gotw/067.htm有一个例子
int main(){  double x = 1e8;  //float x = 1e8;  while( x > 0 )  {    --x;  }}

当你将double改为float时,它在VS2008中是一个无限循环.
根据Gotw的解释:

What if float can’t exactly represent all integer values from 0 to
1e8? Then the modifIEd program will start counting down,but will
eventually reach a value N which can’t be represented and for which
N-1 == N (due to insufficIEnt floating-point precision)… and then
the loop will stay stuck on that value until the machine on which the
program is running runs out of power.

根据我的理解,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中的一个例子全部内容,希望文章能够帮你解决c – Gotw 67中的一个例子所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1233822.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-06
下一篇2022-06-06

发表评论

登录后才能评论

评论列表(0条)

    保存