使用double类型计算2^62到2^0的和结果不准确,原因何在?
问题:使用double类型计算等比数列求和为何结果错误?
我们需要计算等比数列 (2^0 + 2^1 + 2^2 + … + 2^{62}) 的和,先尝试用double类型存储求和结果:
double sum = 0; for (int i = 0; i < 63; i++) { sum += pow(2.0, i); // print("i : $i sum : $sum"); } print(sum);
输出结果:
9223372036854776000.0
显然正确结果应该是奇数,但得到的sum是偶数。改用int类型存储后得到准确结果:
int sum = 0; for (int i = 0; i < 63; i++) { sum += pow(2.0, i).toInt(); //print("i : $i sum : $sum"); } print(sum);
输出结果:
9223372036854775807
原因分析
- double类型的精度限制:double是遵循IEEE 754标准的64位浮点数,其中仅52位用于存储尾数(加上1位隐藏位,共53位有效精度)。这意味着double只能精确表示绝对值在 (-2^{53}) 到 (2^{53}) 之间的整数,超出这个范围的整数无法被精确存储。
- 目标数值的大小:本次计算的和为 (2^{63} - 1),也就是
9223372036854775807,这个数值远大于 (2^{53})(约9007199254740992)。当用double存储这个数时,它只能保存一个最接近的可表示值,也就是输出的9223372036854776000.0,这个值是偶数,与正确结果不符。 - int类型的适配性:这里使用的int是64位有符号整数,其取值范围正好是 (-2^{63}) 到 (2^{63} - 1),完全可以容纳本次计算的结果,因此能精确存储求和值。
内容的提问来源于stack exchange,提问作者user8234870
相关产品推荐
相关产品推荐

