You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

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

火山引擎 最新活动