JavaScript中Math.sqrt(x+1)-Math.sqrt(x)在大x值时返回0的原因咨询
JavaScript中Math.sqrt(x+1)-Math.sqrt(x)在大x值时返回0的原因咨询
嘿,这个问题其实是双精度浮点数的精度限制搞的鬼,咱们一步步拆解来看:
首先得明确:JavaScript里所有数字都是基于IEEE 754标准的64位双精度浮点数。这种格式有个关键特性:它能精确表示的整数范围是-2^53到2^53,一旦整数超过这个范围,相邻的两个整数可能会被存储成同一个浮点数——因为它们之间的差值(1)小于当前数值对应的“最小可分辨单位(ulp)”。
拿你测试的1e16来说,这个数换算成2的幂次大概是2^53.29,已经远超2^53的精确整数范围了。这时候你写x+1(也就是1e16 +1),在JavaScript里会直接被存储为1e16——你可以自己验证一下:
console.log(1e16 === 1e16 + 1); // 输出true
既然x和x+1在浮点数里是同一个值,那Math.sqrt(x+1)和Math.sqrt(x)的结果自然完全相等,相减之后就得到0了,这就是问题的根源。
如果想要避免这个精度损失,咱们可以用数学上的有理化技巧来改写公式:
原来的sqrt(x+1) - sqrt(x),分子分母同乘sqrt(x+1) + sqrt(x),就会变成1/(sqrt(x+1) + sqrt(x))。这个变形后的公式不会出现两个相近数相减的情况,精度损失会小很多。比如改成这样:
function deltaSqrt(x) { return 1 / (Math.sqrt(x + 1) + Math.sqrt(x)); } console.log(deltaSqrt(1e16)); // 输出约5e-9,这才是接近真实值的结果
内容来源于stack exchange
相关产品推荐
相关产品推荐

