我读了here并得出结论,double的最小值(绝对值)是1.7e-308
,但我的代码永远循环:
for (double d(-1.0); d <= 1.0; d+=1.7e-308)
{
}
编辑:我希望以尽可能小的增量从-1.0循环到1.0。
答案 0 :(得分:9)
在C ++ 11 / C99中,您可以使用nextafter
来获取下一个可表示的数字。
#include <cmath>
for (double d(-1.0); d <= 1.0; d = std::nextafter(d, 1.0) )
{
}
此外,如果我正确地进行了数学计算,则在-1和1之间有大约10 ^ 18个可表示的值。
合理假设每秒10 ^ 6个周期,执行此计算需要32000年。
答案 1 :(得分:3)
TL; DR:随着数字变大,计算机能够以浮点数存储的数字之间的差距变大。您的最小数量仅在数字为零时有效。在某些时候,尝试添加这么少的数字并没有任何作用,因为它不能代表如此小的数字变化。
这是因为每个可表示的浮点数之间的差距随着数量的增加而变大。
1与最接近的可表示小于1之间的差值约为1.11×10 -16 ,远大于您尝试添加的值。
所发生的事情是,double存储有一组位用于数字的符号,另一个用于表示数字本身(作为无符号整数)和乘数作为指数2。
当你接近于零时,指数非常小,实际存储数量的一个变化小于你的指数要大得多。
例如,(4 - 3)×2 99 显然会大于(4 - 3)×2 -99 ,这基本上是基本的发生。
当你开始添加时,你会发现最终,添加1.7×10 -308 什么都不做,因为你的当前值是最接近的可表示值,它继续保持不变。无限循环。
请注意,仅当舍入模式设置为roundTiesToEven或roundTiesToAway时,它们才会舍入到最接近的可表示值,除非它们同样接近。
如果您事先用std::fesetround
FE_UPWARD
调用as Marc Glisse noted手动将舍入模式设置为roundTowardPositive,如果添加任何正数(零除外),它将继续增加。我认为roundTowardNegative和roundTowardZero是不言自明的。
答案 2 :(得分:0)
我认为双倍的最小值是1.7e-308,它可能更像-1.7 e308,1.7e-308是一个非常小的数字,但不是负数无穷大的数字。这是一个非常小的数字,接近0。