我尝试在C中计算pow(.1, -120)
并得到:
999999999999993386194947375938605300558731199397053728064304453022541669059515488061520680536169238451435883569728192512.000000
而不是10^120
。有原因吗?在此先感谢您的回复!
答案 0 :(得分:2)
这是由于浮点的不精确性。 double
中没有足够的有效数字来表示该数字,因为数字在内部以二进制形式存储。
例如,如果你运行它:
printf("result=%.10e\n", pow(.1, -120));
printf("result=%.20e\n", pow(.1, -120));
printf("result=%f\n", pow(.1, -120));
printf("10^120=%.10e\n", 1e120);
printf("10^120=%.20e\n", 1e120);
printf("10^120=%f\n", 1e120);
你会得到这个:
result=1.0000000000e+120
result=9.99999999999993386195e+119
result=999999999999993386194947375938605300558731199397053728064304453022541669059515488061520680536169238451435883569728192512.000000
10^120=1.0000000000e+120
10^120=9.99999999999999980003e+119
10^120=999999999999999980003468347394201181668805192897008518188648311830772414627428725464789434929992439754776075181077037056.000000
pow(.1, -120)
与1e120
略有不同的原因是.1
无法正确表示,因此每次迭代时错误都会放大。
另一方面,如果您打印了pow(2, 350)
的结果,则将得到确切答案。
答案 1 :(得分:1)
0.1通常不能完全表示为double
。典型的double
(binary64)可以精确地表示大约2 ^ 64个不同的数字。 0.1不是其中之一。最接近的double
是0.100000000000000005551...
@rici
所以问题是pow(0.100000000000000005551..., -120)
会发生什么?
使用Binomial theorem,这将是
pow(exact_one_tenth, -120)
- 120*pow(exact_one_tenth, -119)*(0.100000000000000005551... - exact_one_tenth)
+ other smaller terms
1e120 - 120*1e119*(0.000000000000000005551...) + other smaller terms
9.99999999999993_3386...e119
// OP result
9.99999999999993_3861...e119
看起来是一个非常准确的答案(匹配16个重要的挖掘。)OP的答案中的下一个较小的double
如下。由于正确的答案受到OP的结果和下一个可表示的数字的限制,并且更接近OP的答案,因此我断言计算结果很好,在0.5 ULP之内。
9.99999999999993_2429...e+119