首页 > 解决方案 > JS浮点导致不正确的舍入 - Math.round() 总是有效?

问题描述

乘法后,我有浮点数的边缘情况。

我必须将数字四舍五入到最接近的百位,但在这种情况下:

115000*4.35 //500249.99999999994

我会得到一个错误的结果:

Math.round(115000*4.35 / 100) * 100 //500200

代替500300

一个解法:

第一次四舍五入到最接近的小数点后一位:

  Math.round(500249.99999999994 * 10) / 10 //200250,

然后四舍五入到最接近的百位:

Math.round(500250 / 100) * 100 //200300

结合:

Math.round(Math.round(num * 10) / 1000) * 100 

有谁知道这是否是一种安全的解决方法?它总是有效吗?

提前致谢!

标签: javascriptfloating-pointmat

解决方案


有谁知道这是否是一种安全的解决方法?它总是有效吗?

这是不安全的,并不总是有效的。

考虑 100,005 • 9.99。在实际算术中,这是 999,049.95,您显然希望将它四舍五入到最接近的 100 的倍数,得到 999,000。

9.99 不能存储在 JavaScript 编号中。最接近的可表示值为 9.9900000000000002131628207280300557613372802734375。在 JavaScript 的浮点运算中将此乘以 100.005 得到 999,049.950000000069849193096160888671875。

您提出的解决方案首先尝试将其四舍五入到最接近的 1/10 倍数。在这种情况下,它成功了,产生了 999,050。(在许多情况下,这会失败,因为唯一可以表示的 1/10 的倍数是 5/10 的倍数。)然后使用Math.round(999050 / 100) * 100)收益率 999,100(因为Math.round向上舍入一半)。

即使使用真正的算术而不是浮点算术,您提出的解决方案也行不通。使用相同的方法将 999,049.95 四舍五入到最接近的 1/10 倍数(一半以上)得到 999,050,然后将其四舍五入到最接近的 100 倍数得到 999,100。


推荐阅读