提问人:Jeroen Ooms 提问时间:7/28/2012 最后编辑:Eric LeschinskiJeroen Ooms 更新时间:9/7/2023 访问量:284450
在 Javascript 中处理浮点精度 [duplicate]
Dealing with float precision in Javascript [duplicate]
问:
我在javascript中有大量的数值。我想通过将它们向下舍入到最接近的倍数来对它们进行分组,并将结果转换为字符串。y
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
答:
181赞
Rusty Fausak
7/28/2012
#1
来自这篇文章: 如何处理 JavaScript 中的浮点数精度?
您有以下几种选择:
- 对小数使用特殊数据类型,如 decimal.js
- 将结果格式化为固定数量的有效数字,如下所示:
(Math.floor(y/x) * x).toFixed(2)
- 将所有数字转换为整数
评论
15赞
Karl
12/23/2014
“将所有数字转换为整数”,我一直想知道这一点。众所周知,JavaScript 有一种数字类型,即 IEEE 754 浮点数。如果是这样的话,那么为什么将浮点数转换为整数是有效的,(而且确实如此)?JavaScript 是否真的有一个根本无法通过保留字访问的整数数据类型?Number
7赞
rich remer
12/8/2015
IEEE 754 可以精确地表示高达 2^50 的整数。因此,如果您在已知范围内工作,则可以缩放值以利用 50 位(或其他)精度,而不是浪费通常为大数字保留的精度。
1赞
paul23
12/8/2017
@richremer浮点具有精度(对于正常值)不依赖于大小的属性。- 因此,无论您将其转换为整数(例如,将值乘以某个常数),精度都是相等的。
0赞
Rivenfall
7/15/2020
“有效位数”是使用科学记数法(无前导零或尾随零)的位数,它是根据情况做出的选择。- toPrecision 的参数似乎是一些有效数字。- toFixed 表示多个尾随数字。
3赞
jefelewis
12/4/2020
toFixed() 会将数字转换为字符串。
1赞
whaatt
7/28/2012
#2
在完成这项任务时,我首先会找到 中的小数位数,然后相应地四舍五入。我会使用:x
y
y.toFixed(x.toString().split(".")[1].length);
它应该转换为字符串,将其拆分到小数点上,找到右侧部分的长度,然后应根据该长度四舍五入。x
y.toFixed(length)
y
评论
4赞
Jeroen Ooms
7/28/2012
这是一个整数,这有点问题。x
0赞
user56reinstatemonica8
11/21/2022
适用于浮点数和整数的现代 (>ES2020) 版本:Number(x.toFixed(String(y).split('.')[1]?.length ?? 0)
6赞
philipvr
7/28/2012
#3
你可以做这样的事情:
> +(Math.floor(y/x)*x).toFixed(15);
1.2
编辑:最好使用big.js。
big.js
一个小巧、快速、易于使用的库,用于任意精度的十进制算术。
>> bigX = new Big(x)
>> bigY = new Big(y)
>> bigY.div(bigX).round().times(bigX).toNumber() // => 1.2
评论
0赞
Jeroen Ooms
7/28/2012
不适用于所有组合和 .y
x
9赞
dopatraman
8/30/2018
toFixed 返回一个字符串
0赞
Rivenfall
7/15/2020
如果可以的话,将 floor 替换为 round、parseFloat 和 15 替换为较小的数字(toFixed 参数可以根据 x 计算)+
0赞
fider
1/19/2023
还要检查十进制 .js 或 dinero.js 中的 $
2赞
prahaladp
4/9/2013
#4
看看这个链接..这对我帮助很大。
http://www.w3schools.com/jsref/jsref_toprecision.asp
该函数返回一个,因此不要忘记使用该函数转换为所需精度的小数点。toPrecision(no_of_digits_required)
string
parseFloat()
评论
1赞
prahaladp
3/7/2018
如果你碰巧是对我这个答案投反对票的人,你能解释一下为什么吗?(提供的解决方案似乎有效)
0赞
Rivenfall
7/16/2020
基本上问题是这样的,你有 js 数字 y 和 x,你想要最接近的 x 倍数(从 y)。toPrecision 方法无济于事,即parseFloat((150).toPrecision(1)) === 200
0赞
Tchakabam
1/25/2022
对舍入问题进行字符串/浮点解析转换并不完全是我所说的大规模执行:D(更好:实现/使用仅对数字进行操作/返回的 toPrecision 函数!
5赞
Hamza Alayed
3/19/2014
#5
> 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
You can check the full explanation here.
评论
0赞
joe cool
4/25/2019
Math.m(0.07, 100) => 7.000000000000002
0赞
shaiis.com
12/30/2020
This is not working!
评论
double
y
"1.2"
Math.floor(y)