javascript - 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
有谁知道这是否是一种安全的解决方法?它总是有效吗?
提前致谢!
解决方案
有谁知道这是否是一种安全的解决方法?它总是有效吗?
这是不安全的,并不总是有效的。
考虑 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。
推荐阅读
- python-3.7 - def 关键字似乎总是给我一个错误反馈
- apache-camel - Camel PAHO 路由在连接回来时未收到离线消息
- java - 需要序列化的 EnqueueWork 导致 AsyncTask 崩溃
- opencv - 如何从 opencv.js 中找到角向量
- c++ - OpenAL 读取 WAV 文件库
- winforms - 在 PowerShell 中为新表单分离任务栏图标
- javascript - 如何从单独的组件传入道具?
- excel - 基于多列多IF条件的TEXTJOIN
- javascript - 如何修复下拉列表以使隐藏的 div 之一出现并附加
- r - 如何对数据框中的每一行执行条件求和/均值