处理 Javascript 中的浮点精度

IT技术 javascript floating-point double floating-accuracy numerical-methods
2021-02-04 18:49:24

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

如何解决烦人的浮点精度?

例如:

0.2 + 0.4 = 0.6000000000000001

我尝试过的两件事:

>>> y = 1.23456789 
>>> x = 0.2 
>>> parseInt(Math.round(Math.floor(y/x))) * x; 
1.2000000000000002

和:

>>> y = 1.23456789 
>>> x = 0.2 
>>> y - (y % x)
1.2000000000000002
5个回答

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

您有几个选择:

  • 使用特殊的小数数据类型,如decimal.js
  • 将您的结果格式化为一些固定数量的有效数字,如下所示: (Math.floor(y/x) * x).toFixed(2)
  • 将所有数字转换为整数
toFixed() 会将数字转换为字符串。
2021-03-14 18:49:24
“将所有数字转换为整数”,我对此感到疑惑。众所周知,JavaScript 有一种数字类型Number,即 IEEE 754 浮点数。如果是这样,那么为什么将浮点数转换为整数会起作用(并且确实如此)?JavaScript 是否真的有一个不能通过保留字访问的整数数据类型?
2021-03-30 18:49:24
@richremer 浮点数具有精度(对于正常值)不依赖于大小的属性。- 因此,无论您将其转换为整数(例如将值与某个常数相乘),精度都是相等的。
2021-03-30 18:49:24
IEEE 754 可以精确地表示高达 2^50 之类的整数。因此,如果您在已知范围内工作,则可以缩放值以利用 50 位(或其他)精度,而不是浪费通常为大数保留的精度。
2021-04-07 18:49:24
“有效数字”的数量是使用科学记数法(无前导零或尾随零)的数字数量,它是根据情况选择的。- toPrecision 的参数似乎是一些有效数字。- toFixed 用于多个尾随数字。
2021-04-10 18:49:24

你可以这样做

> +(Math.floor(y/x)*x).toFixed(15);
1.2

编辑:最好使用 big.js。

大.js

用于任意精度十进制算术的小型、快速、易于使用的库。

>> bigX = new Big(x)
>> bigY = new Big(y)
>> bigY.div(bigX).round().times(bigX).toNumber() // => 1.2
+如果可以的话,用圆形替换地板,用 parseFloat 和 15 用较低的数字替换(toFixed 参数可以基于 x 计算)
2021-03-16 18:49:24
不适用于所有组合yx.
2021-03-21 18:49:24
toFixed 返回一个字符串
2021-03-27 18:49:24
> var x = 0.1
> var y = 0.2
> var cf = 10
> x * y
0.020000000000000004
> (x * cf) * (y * cf) / (cf * cf)
0.02

快速解决方案:

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

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

这是行不通的!
2021-03-12 18:49:24
我的荣幸 :-)
2021-03-13 18:49:24
Math.m(0.07, 100) => 7.000000000000002
2021-04-02 18:49:24

看看这个链接..它帮了我很多。

http://www.w3schools.com/jsref/jsref_toprecision.asp

toPrecision(no_of_digits_required)函数返回一个string所以不要忘记使用该parseFloat()函数转换为所需精度的小数点。

如果您碰巧是对我的这个答案投反对票的人,请您解释一下原因吗?(提供的解决方案似乎有效)
2021-04-02 18:49:24
基本上问题是这样的,您有 js 数字 y 和 x,并且您想要 x 的最接近(从 y)倍数。toPrecision 方法没有帮助,即parseFloat((150).toPrecision(1)) === 200
2021-04-08 18:49:24

处理这个任务时,我会先找到 中的小数位数x,然后y相应四舍五入我会用:

y.toFixed(x.toString().split(".")[1].length);

它应该转换x为一个字符串,将其拆分到小数点上,找到正确部分的长度,然后根据该长度进行y.toFixed(length)舍入y

x是一个整数有点问题
2021-03-19 18:49:24