为什么节点不评估Math.tan(Math.PI/2)到无穷大,但Chrome V8确实如此

Why does node not evaluate Math.tan(Math.PI/2) to Infinity but Chrome V8 does?

本文关键字:Math Chrome 无穷大 V8 评估 节点 tan PI 为什么      更新时间:2023-09-26

当在节点命令行界面运行此命令时:

> Math.tan(Math.PI/2)
16331778728383844 

但是在Chrome中:

> Math.tan(Math.PI/2)
Infinity

不都使用相同的V8引擎?

Node的结果甚至不等于JavaScript中最大的"整型"值

如果您查看Math对象的v8实现,您会看到:

function MathTan(x) {
  return MathSin(x) / MathCos(x);
}

事实上,Math.cos(Math.PI/2)在Node中也返回了一个不寻常的值(实际上,是您不寻常的Math.tan结果的倒数):

> Math.cos(Math.PI/2)
6.123031769111886e-17  // in Chrome, this is 0

所以,你的问题简化为:为什么Math.cos(Math.PI/2)在节点<=0.10.24中不为零?

这个问题很难回答。正弦和余弦的实现是由一个名为TrigonometricInterpolation的数学繁重的函数提供的,它依赖于一个由c++代码生成的1800个样本值的反向查找表,该代码本身是在v8首次安装时生成的Python脚本。

值得注意的是,当前的三角查找表代码最近替换了一个旧的查找表,所以当前版本的Node可能不会使用最新的三角查找表(因为新代码于2013年11月22日到达v8,但在2013年12月0.10.24版本之前,唯一从v8拉入Node的是2013年11月11日,也就是更改前11天)。Chrome可能正在使用最新的代码,而当前稳定节点使用不同的三角函数代码。

如果您输入:

Math.PI/2

你能精确地得到π/2吗?不,)

因此,它不能"准确"地将Math.tan(Math.PI/2)计算为Infinity,因为它没有Math.PI/2的精度。

但在某些情况下(如Chrome),精度的损失是如此之小,它得到Infinity

为了说明这一点,请看下面的控制台输出:
Math.PI/2  
> 1.5707963267948966  
Math.tan(1.5707963267948964)  
> 5039790063769915  
Math.tan(1.5707963267948965)  
> Infinity  
Math.tan(1.5707963267948966)  
> Infinity  
Math.tan(1.5707963267948967)  
> -5039790063769915

注意到实际上有两个值导致Infinity吗?

问题是,服务器与浏览器的设置不同。无穷大是变量"数"。POSITIVE_INFINITY",但是如果你检查另一个变量,"Number. infinity"。MAX_INTEGER" my chrome gives:

console.log( Number.MAX_INTEGER ) // prints 9007199254740991

和9007199254740991小于16331778728383844,所以可能chrome决定每个比number大的数字。MAX_INTEGER为无穷大

在节点js上console.log(数量。MAX_INTEGER)//打印1.7976931348623157e+308

Chrome和node js对数字有不同的上下限制。

综上所述,在nodejs上 Number.MAX_INTEGER 大于 Math.tan(Math.PI/2)chromeNumber.MAX_INTEGER 小于 Math.tan(Math.PI/2)

所以nodejs看到一个数字chrome看到Infinity

带有HEAD版本

node -v
v0.11.14-pre
node
> Math.tan(Math.PI/2)
Infinity
https://github.com/joyent/node/issues/7852