Math.cos(Math.PI / 2)在JavaScript&中返回6.123031769111886e-17。 AS3?

时间:2011-11-08 12:57:57

标签: javascript flash actionscript-3 ecmascript-5

如果我理解这是正确的,那么JavaScript和ActionScript 3都可以使用弧度。

因此以下代码的预期输出为:

Math.PI                 //Expected 3.141592653589793, got 3.141592653589793

Math.sin(0)             //Expected 0, got 0
Math.sin(Math.PI/2)     //Expected 1, got 1
Math.sin(Math.PI)       //Expected 0, got 1.2246063538223773e-16
Math.sin(Math.PI*3/2)   //Expected -1, got -1
Math.sin(Math.PI*2)     //Expected 0, got -2.4492127076447545e-16

Math.cos(0)             //Expected 1, got 1
Math.cos(Math.PI/2)     //Expected 0, got 6.123031769111886e-17
Math.cos(Math.PI)       //Expected -1, got -1
Math.cos(Math.PI*3/2)   //Expected 0, got -1.836909530733566e-16
Math.cos(Math.PI*2)     //Expected 1, got 1

这与Firefox,Chrome,Safari以及Flash Professional CS5.5中的行为相同。我使用的是Mac OS X 10.7.2。

测试:

http://jsfiddle.net/KA4VM/

5 个答案:

答案 0 :(得分:17)

你看过你得到的价值了吗?你期待0,但你得到像

这样的东西
0.00000000000000012246063538223773

对你来说,这还不够零吗?

基本上,当您的输入无法表示为精确的二进制值时,您不应期望二进制浮点运算正好正确 - 如果它不合理,则pi / 2不能表示。 (即使输出可以精确地以二进制表示,如果输出无法准确表达,您也不应期望结果是准确的...)

答案 1 :(得分:2)

Math.PI不是pi的100%准确表示,仅仅是因为pi是非理性的,浮点数只是到目前为止。

因此,由于四舍五入的错误,你会得到非常小的数字(你的数字是#。##### e-16和#。##### e-17,这很小)。

你无能为力,但接受0.000000000000000006足够接近0。

答案 2 :(得分:1)

所以你有1.xxxxx * 10 ^ -16

这将是0.0000000000000001xxx(小数点后十五个零)

我敢打赌,它足够接近零,将其视为0。

由于pi值的误差,你得到了这个无穷小的错误(你应该知道,它会延伸到小数点后的无穷大数字)

你没有提到,如果你在AS3或JavaScript中得到这个,但

答案 3 :(得分:1)

因为PI是一个无理数(没有理性的实数,所以不可能用精确值来计算。 就像Jon Skeet所说的那样,Math-object的三角函数方法只得到PI的近似值并返回一个近似值。 如果零值的返回对您的代码很重要,则必须对它们进行舍入。 在这种情况下,为方便起见,我通过自己的方法扩展这些Javascript对象:

Math.Sin = function(w){         
    return parseFloat(Math.sin(w).toFixed(10));
};

现在,当你得到

Math.sin(Math.PI)

这个奇怪的结果

> 1.2246467991473532e-16

你得到了你所期望的

Math.Sin(Math.PI)
> 0

对其他三角函数执行相同的操作:

Math.Cos = function(w){ 
    return parseFloat(Math.cos(w).toFixed(10));
};

等等。

答案 4 :(得分:1)

考虑这些错误都小于1e-15,大约为2**(-50),因此我们可以添加一个数字2**3的数字来舍入结果。因此,如果我们选择8作为数字,我们可以重新定义sincos,如下所示:

function sin(x) {
  return Math.sin(x) + 8 - 8;
}

function cos(x) {
  return Math.cos(x) + 8 - 8;
}

这应该是错误的结果,并且比toFixed方法更快。