javascript - Javascript 浮点数会根据您输入变量的方式改变准确性
问题描述
编辑:这不是关于 JS 中的浮点实现有多好或多坏的讨论。这是一个非常具体的案例,因此请不要将其标记为与浮点讨论的重复。
这是我用来计算以美分表示的金额的小数部分的脚本(例如 3.34 是 334 美分):
const amount = 334;
const decimal = Math.trunc(100 * ((amount / 100) % 1).toFixed(2));
console.log(decimal); //34
到目前为止,一切都很好。如果将金额更改为 329,则会得到 28,这是错误的:
const amount = 329;
const decimal = Math.trunc(100 * ((amount / 100) % 1).toFixed(2));
console.log(decimal); //28
这是因为 ,(329/100) % 1 = 0.29000000000000004
而不是0.30
, 因为 JS 浮点很烂?
但是对我来说真正疯狂的是,在开发一个循环来查看该脚本使用 FOR 中断的情况时,它并没有在 329 上中断!:
for(let x = 325; x < 335; x++) {
const r = Math.trunc((100 * (( x / 100) % 1)).toFixed(2));
console.log(x, r);
}
我在这里想念什么?为什么在循环内工作而直接调用函数时不工作?您如何以稳健可靠的方式进行计算?
解决方案
对此进行分析:
const amount = 329;
const decimal = Math.trunc(100 * ((amount / 100) % 1).toFixed(2));
(((329/100) % 1).toFixed(2))
返回字符串"0.29"
- 如果将其转换回 ta 数字,则将其扫描到最接近的可能浮点数 0.289999999999999980。您可以通过以下方式证明:
(+(((329/100) % 1).toFixed(2))).toPrecision(18)
- 然后将结果乘以 100 并截断,得到正确的值 28。
toFixed()
类似或的函数toPrecision()
旨在为最终输出格式化数字,但不适用于数学计算。
为您解决问题:
const amount = 329;
const decimal = amount % 100;
...或者如果数量可以是带有分数的浮点数。
const decimal = math.round(amount) % 100;
最后一点:这是关于浮点实现以及如何使用它的讨论;不仅适用于 JS!