JavaScript中的精确浮点算法

JavaScript中的精确浮点算法,javascript,floating-point,modulus,Javascript,Floating Point,Modulus,我正在用JavaScript创建数字微调器小部件,以模拟webkit中的数字字段 更改数字时,需要检查该值是否不仅在可接受的范围内,而且是否在步骤中: <input type="number" min="0" max="100" step="1" /> 尽管出于测试目的,您可以简单地使用: function checkStep(val, min, step) { var ret, diff, moddedDiff; diff = va

我正在用JavaScript创建数字微调器小部件,以模拟webkit中的数字字段

更改数字时,需要检查该值是否不仅在可接受的范围内,而且是否在步骤中:

<input type="number" min="0" max="100" step="1" />
尽管出于测试目的,您可以简单地使用:

function checkStep(val, min, step) {
    var ret,
        diff,
        moddedDiff;
    diff = val - min;
    moddedDiff = diff % step;
    ret = val - moddedDiff;
    return ret;
}
这对于整数和更大的值非常有效,但是由于JavaScript处理浮点数的方式,我遇到了小数的问题

例如:

checkStep(0.5, 0, 0.1) //returns 0.4, 0.5 is expected
function checkStep(val, min, step) {
  var ret,
    diff,
    moddedDiff;
  var pows = 0;
  while( step < 1 ) { // make sure step is > 1
    step *= 10;
    val *= 10;
    min *= 10;
    pows++;
  }
  diff = val - min;
  moddedDiff = diff % step;
  ret = val - moddedDiff;
  return ret / Math.pow( 10, pows );
}
在分析每一行时,JavaScript中的
0.5%0.1
返回
0.0999999998

如何使此函数更精确*



*精确的是,它适用于
0.01
及以上的增量。

没有绝对保证精确的浮点计算。改用整数计算。在0.1示例中,您可以以整数形式计算“0.1”的数量,直观地在用户的最后一位之前添加点。

您可以尝试确保步长大于1(通过重复乘以10),然后执行模数,然后缩小到原始值。例如:

checkStep(0.5, 0, 0.1) //returns 0.4, 0.5 is expected
function checkStep(val, min, step) {
  var ret,
    diff,
    moddedDiff;
  var pows = 0;
  while( step < 1 ) { // make sure step is > 1
    step *= 10;
    val *= 10;
    min *= 10;
    pows++;
  }
  diff = val - min;
  moddedDiff = diff % step;
  ret = val - moddedDiff;
  return ret / Math.pow( 10, pows );
}
功能检查步骤(val、min、step){
var ret,
差异,
moddedDiff;
var-pows=0;
而(步骤<1){//确保步骤>1
步骤*=10;
val*=10;
最小*=10;
pows++;
}
diff=val-min;
moddedDiff=差分百分比步长;
ret=val-moddedDiff;
返回ret/Math.pow(10,pow);
}
这适用于您提供的示例,但我不能保证它适用于所有情况。请参见此处的JSFIDLE:


没有所谓的“精确”浮点。它们都是尽力而为的近似值。你最多可以指定一个你愿意接受的精度级别。@MarcB,说得好,忘了提到我对这项工作的兴趣达到百分之一百。“JavaScript中的0.5%0.1返回0.0999999998。”哦,这只是冰山一角
0.1+0.2=0.300000000004
@T.J.Crowder,是的,是的,我很清楚浮点运算中的标准错误,我只是不确定在这种情况下如何解释。我发现你的例子有点让人困惑。对于步骤2和输入5.5,它不应该返回6而不是4吗?5.5比4更接近6。同样,0.5的步长和0.1的输入不应该返回0吗,因为0.1比0.5更接近于0?有趣的是,你说精度没有保证,因为浮点运算定义良好,在每个浏览器中产生相同的结果。问题是,这通常是违反直觉的。我真的希望得到帮助,使浮点算术代码更具弹性,并使其在合理的人类范围内工作当然,每次在里面都是一样的,我打算用一些更新的代码更新我的答案。我基本上也在做同样的事情,但是使用递归函数调用。到目前为止,这似乎是可行的,尽管还需要进行一些模数检查。