【问题标题】:Accurate floating point arithmetic in JavaScriptJavaScript 中的精确浮点运算
【发布时间】:2012-04-27 16:12:01
【问题描述】:

我正在 JavaScript 中创建数字微调器小部件,以从本质上模仿 webkit 中的数字字段。

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

<input type="number" min="0" max="100" step="1" />

如果用户输入5.5,该字段会将其截断为低于该值的最接近的步长,在本例中为5

对于2的步骤,如果用户输入5.5,结果将是4

我计划用于此计算的方程式如下所示:

...code...
_checkStep: function (val) {
    val ret,
        diff,
        moddedDiff;
    diff = val - this._min;
    moddedDiff = diff % this._step;
    ret = val - moddedDiff;
    return ret;
},
//set elsewhere
_min,
_step,
...more code...

尽管出于测试目的,您可以简单地使用:

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

在分析每一行时,发现 JavaScript 中的 0.5 % 0.1 返回 0.09999999999999998

怎样做才能使这个函数更准确*?


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

【问题讨论】:

  • 没有“准确”的浮点数。它们总是尽力而为的近似值。您最多可以指定您愿意接受的精度水平。
  • @MarcB,好点子,忘了说我有兴趣将这项工作提高到百分之一。
  • “JavaScript 中的 0.5 % 0.1 返回 0.09999999999999998。” 哦,这只是冰山一角。 0.1 + 0.2 = 0.30000000000000004.
  • @T.J.Crowder,是的,是的,我很清楚浮点运算中的标准不准确性,我只是不确定在这种情况下如何解释它们。
  • 我觉得你的例子有点混乱。对于 2 的步长和 5.5 的输入,它不应该返回 6,而不是 4? 5.5 比 4 更接近 6。同样,0.5 的步长和 0.1 的输入不应该返回 0,因为 0.1 比 0.5 更接近 0?

标签: javascript floating-point modulus


【解决方案1】:

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

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 );
}

这适用于您提供的示例,但我不能保证它适用于所有示例。在此处查看 jsfiddle:

http://jsfiddle.net/bCTL6/2/

【讨论】:

  • 我打算用一些更新的代码来更新我的答案。我基本上在做同样的事情,但是使用递归函数调用。到目前为止,它似乎有效,尽管还需要进行一些模数检查。
【解决方案2】:

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

【讨论】:

  • 有趣的是,您说不能保证准确性,因为浮点运算定义明确并且在每个浏览器中产生相同的结果。问题是它经常违反直觉。我真的希望获得帮助,使浮点算术代码更具弹性,并使其适用于合理的人类范围。
  • 嗯,我的意思是“从人类小数点来看”的准确性,是的。 :) 当然,它每次在内部总是以完全相同的方式工作。
猜你喜欢
  • 1970-01-01
  • 2016-11-06
  • 2016-11-22
  • 2020-09-24
  • 2020-12-17
  • 1970-01-01
  • 2014-10-07
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多