客户坚持认为sin(Math.PI)和cos(Math.PI / 2)应该返回零,而不是大约10 ^ -16。他对Math.sin()和Math.cos()的解释不满意,不仅在Javascript中,而且在所有其他语言中。
我发现的一件事是,Math.sin()对小于2e-16的参数变化不敏感:
Math.sin(Math.PI)
1.2246063538223773e-16
Math.sin(Math.PI + 1e-16)
1.2246063538223773e-16
Math.sin(Math.PI + 2e-16)
1.2246063538223773e-16
Math.sin(Math.PI + 3e-16)
-3.216285744678249e-16
因为当sin(x)接近零时sin(x)〜= x,所以当x小于2e-16时,我发现sin(x)为零。
Math.cos()更精确,它对高达1.1e16 的变化不敏感(编辑:它发生因为基值较小:Math.PI / 2)所以我会施展cos (x)当它小于1e-16时为零:
Math.cos(Math.PI / 2)
6.123031769111886e-17
Math.cos(Math.PI / 2 + 1e-16)
6.123031769111886e-17
Math.cos(Math.PI / 2 + 1.1e-16)
6.123031769111886e-17
Math.cos(Math.PI / 2 + 1.5e-16)
-1.6081428723391245e-16
当然,当x-> 0时,这样的演员会毁掉sin(x)的原始精度:
Math.sin(1e-99)
1e-99
Math.sin(1e-50)
1e-50
Math.sin(1e-40)
1e-40
Math.sin(1e-20)
1e-20
Math.sin(1e-10)
1e-10
Math.sin(1e-5)
0.000009999999999833334
但是如果应用程序使用这么小的角度,应该直接使用x,而不是sin(x),对吗?因为sin(x)在这个范围内总是倾向于x。
考虑到应用程序有10位数的UI精度,你觉得我的策略是对的吗?
答案 0 :(得分:2)
你可以决定你想要归零的接近零 -
Number.prototype.rounded= function(i){
i= Math.pow(10, i || 15);
// default
return Math.round(this*i)/i;
}
Math.sin(Math.PI).rounded()
/* returned value: (Number) 0 */
Math.PI.rounded(5)
/* returned value: (Number) 3.14159 */