Dart中为何整数加1无效果、加2却生效?求技术解答
为什么Dart中给2^53加1无效果,加2却生效?
嘿,这个问题刚好戳中了Dart里数值类型的一个关键细节,我来帮你理清楚背后的原因:
核心问题:pow(2,53)返回的是double,不是int
你可能以为pow(2,53)会返回一个int,但实际上dart:math里的pow函数返回的是num类型,对于2的53次方这个值,它会以**64位双精度浮点数(double)**的形式返回。哪怕你把它赋值给int变量,后续如果操作逻辑依赖了double的特性,还是会触发精度限制——不过更可能的是你代码里的变量实际是double类型(比如用var声明而非int),这才导致了看到的现象。
double的精度限制:2^53是精确整数的临界点
64位double遵循IEEE 754标准,它的存储结构决定了:
- 它能精确表示的最大整数是
2^53(也就是你打印的9007199254740992)。 - 超过这个数值后,并不是所有整数都能被精确存储。简单来说,每两个可精确表示的整数之间会间隔2、4甚至更大的数——因为double的尾数只有52位,加上隐含的1位,总共53位的精度。
所以:
- 当你给
2^53的double值加1时,2^53 +1这个数无法被double精确表示,计算机会自动把它舍入到最近的可表示的double值,也就是原来的2^53,所以打印出来和之前的数值一模一样。 - 而
2^53 +2刚好是符合double存储规则的数(它是2的倍数,能被尾数部分精确表示),所以加2之后能得到正确的结果。
如何用Dart的任意精度int实现正确的运算
如果你想利用Dart任意精度int的特性来计算,应该直接用整数运算,而不是pow函数,比如:
void main() { // 用位移运算得到2^53的int值 int ov = 1 << 53; print('$ov'); // 9007199254740992 ov = ov + 1; print('$ov'); // 9007199254740993 ov = ov + 2; print('$ov'); // 9007199254740995 }
这样所有的运算都是基于任意精度的int,就不会出现精度丢失的问题了。
内容的提问来源于stack exchange,提问作者Mister Smith




