近似sin()到{1,0,-1}给出了错误的结果

时间:2015-02-04 07:10:28

标签: javascript trigonometry rounding-error

我正在尝试创建一个与sin()近似的函数,以便它取值1,0或-1。这段代码

var periodicity = 2 * Math.PI;   
var sin3 = function(t) {
  var tmod = (t / periodicity) % 1;
  if (tmod < 1/8)
    return 0
  else if (tmod < 3/8)
    return Math.sign(tmod)
  else if (tmod < 5/8)
    return 0
  else if (tmod < 7/8)
    return -Math.sign(tmod)
  else return 0;
}

有一个问题,当一个变量是一个整数/ 8时,它有时会得到一个不一致的值。例如代码

for (i = 0; i < 32; i++) {
  sin3(i/8*2*Math.PI)
}

获取值

[0,1,1,0,0,-1,-1,0,0,1,1, 1 ,0,-1,-1, -1 ,0,1,1,0,0,-1,-1,0,0,1,1,0,0,-1,-1,0

第12个元素应为0但变为1。 第16个元素应为0但变为-1。

将周期性更改为1无济于事。使用增量2 ^ -n应该在二进制架构上精确,我想。

这是一个小提琴http://jsfiddle.net/ephyckf1/1/

1 个答案:

答案 0 :(得分:0)

就像你说的那样,i/8有一个精确的二进制表示 因此,(i/8) * ((2*Math.PI) / (2*Math.PI))不会受到浮点舍入错误的影响,但(i/8*2*Math.PI) / (2*Math.PI) 。这是因为中间结果(i/8*2*Math.PI)没有精确的浮点表示。

话虽如此,你为何费心?对于i的每个奇数值(包括第12和第16个元素),在两个不同的近似值之间的边界上精确,因此无论哪个返回都是任意的。