#include <iostream>
#include <limits>
int main()
{
double d = std::numeric_limits<double>::max();
std::cout << std::to_string(d) << std::endl;
std::cout << std::to_string(d - 1) << std::endl;
}
[test@arch_host ~]$ g++ test.cpp [test@arch_host ~]$ ./a.out 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
为什么第二个不以7结尾?
答案 0 :(得分:6)
double
正在使用IEEE 754标准进行表示。与int
不同,没有固定的最小步长1.相反,当数量越大,最小步长越大:
你的数字的值是如此之大,以至于步长大于1.为了保持简单,我们假设它是10.因此,如果你试图减去1,则值将四舍五入为下一个有效的双精度值。这和以前一样。
或者换句话说:17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873817718091929988125040402618412485836
7 不是有效的双倍。
答案 1 :(得分:2)
C ++中的double是最常见的符合I64 754格式的二进制64格式。因此我们将基于此回答。它也适用于其他浮点格式,例如float(binary32),binary16,它没有本机C ++类型,甚至非IEEE 754浮点格式。你的双重由一个52位的尾数和一个11的指数组成,它的范围是&#34;动态的&#34; :
如果指数大:尾数将代表整数,那么,之后,它不能代表例如,尾随2,因为限制数量为尾数上的数字。
如果指数是小:尾数将代表越来越小的负幂2(1 / 2,1 / 4等......),它会更精确。
问题本身: 如果没有指定IEEE 754中定义的其中一种舍入模式,则默认为&#34; round-to-nearest-even&#34 ;,这正是听起来的样子。
当您使用最大双精度值运算时,它与最后一个可表示的双精度之间的差距很大。因此,减去1.0,代数给出maxDouble - 1.0,但是在硬件中,它是不可表示的,对于指数来说太小了(它会反映在第52位之后的变化中),所以你的FPU使用圆形到最近的均匀舍入模式, 和舍入到maxDouble。
要解决您的问题,您可以使用两种解决方案。如果程序计算的值范围不是太大,并且计算速度不是太高的要求,则使用定点算术。或者使用CPU制造商提供的内在函数(通常在头文件中找到)来将舍入模式设置为向0舍入或向下舍入。
哦,这里有一个舍入模式的简短列表:舍入到最近的偶数,向上舍入,向下舍入并向0舍入,这相当于向上或向下舍入,具体取决于操作的符号。
并且,如果您要使用浮点运算中的高值进行编码,则应定期检查您的数字是否已经饱和到∞或-∞,因为那样您就无法对它们应用操作