在Javascript中处理浮点精度

Jer*_*oen 83 javascript floating-point double floating-accuracy numerical-methods

y在javascript中有大量的数值.我想通过将它们舍入到最接近的倍数来对它们进行分组x,并将结果转换为字符串.

如何绕过恼人的浮点精度?

例如:

0.2 + 0.4 = 0.6000000000000001
Run Code Online (Sandbox Code Playgroud)

我尝试了两件事:

>>> y = 1.23456789 
>>> x = 0.2 
>>> parseInt(Math.round(Math.floor(y/x))) * x; 
1.2000000000000002
Run Code Online (Sandbox Code Playgroud)

和:

>>> y = 1.23456789 
>>> x = 0.2 
>>> y - (y % x)
1.2000000000000002
Run Code Online (Sandbox Code Playgroud)

Rus*_*sak 115

从这篇文章:如何处理JavaScript中的浮点数精度?

你有几个选择:

  • 使用特殊的小数数据类型,如decimal.js
  • 将结果格式化为固定数量的有效数字,如下所示: (Math.floor(y/x) * x).toFixed(2)
  • 将所有数字转换为整数

  • "将所有数字转换为整数",我对此感到疑惑.我们知道,JavaScript有一个数字类型`Number`,一个IEEE 754浮点数.如果是这种情况,那么为什么将浮点数转换为整数?(它确实如此)?JavaScript实际上是否具有通过保留字无法访问的整数数据类型? (13认同)
  • IEEE 754可以精确地表示类似2 ^ 50的整数.因此,如果您在一个已知范围内工作,您可以缩放您的值以利用50位(或其他)精度,而不是浪费通常为大数字保留的精度. (4认同)
  • toFixed() 会将数字转换为字符串。 (3认同)

phi*_*pvr 5

您可以执行以下操作:

> +(Math.floor(y/x)*x).toFixed(15);
1.2
Run Code Online (Sandbox Code Playgroud)

  • toFixed 返回一个字符串 (7认同)

Ham*_*yed 5

> var x = 0.1
> var y = 0.2
> var cf = 10
> x * y
0.020000000000000004
> (x * cf) * (y * cf) / (cf * cf)
0.02
Run Code Online (Sandbox Code Playgroud)

快速解决方案

var _cf = (function() {
  function _shift(x) {
    var parts = x.toString().split('.');
    return (parts.length < 2) ? 1 : Math.pow(10, parts[1].length);
  }
  return function() { 
    return Array.prototype.reduce.call(arguments, function (prev, next) { return prev === undefined || next === undefined ? undefined : Math.max(prev, _shift (next)); }, -Infinity);
  };
})();

Math.a = function () {
  var f = _cf.apply(null, arguments); if(f === undefined) return undefined;
  function cb(x, y, i, o) { return x + f * y; }
  return Array.prototype.reduce.call(arguments, cb, 0) / f;
};

Math.s = function (l,r) { var f = _cf(l,r); return (l * f - r * f) / f; };

Math.m = function () {
  var f = _cf.apply(null, arguments);
  function cb(x, y, i, o) { return (x*f) * (y*f) / (f * f); }
  return Array.prototype.reduce.call(arguments, cb, 1);
};

Math.d = function (l,r) { var f = _cf(l,r); return (l * f) / (r * f); };

> Math.m(0.1, 0.2)
0.02
Run Code Online (Sandbox Code Playgroud)

您可以在此处查看完整说明.