简体   繁体   English

导致不正确舍入的 JS 浮点数 - Math.round() 总是有效?

[英]JS floating point causing incorrect rounding - Math.round() always works?

I have edge cases with floats after multiplying.乘法后我有带浮点数的边缘情况。

I have to round numbers to the nearest hundred, but in cases like that:我必须将数字四舍五入到最接近的百位,但在这种情况下:

115000*4.35 //500249.99999999994

I'll get a wrong result:我会得到一个错误的结果:

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

instead of 500300而不是500300

A solution:一个解法:

First rounding to the nearest one decimal place:第一次四舍五入到最接近的一位小数:

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

then rounding to the nearest hundred:然后四舍五入到最近的百位:

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

combined:合并:

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

Does anyone know if it's a safe way to solve it?有谁知道这是否是解决问题的安全方法? Does it always work?它总是有效吗?

Thanks in advance!提前致谢!

Does anyone know if it's a safe way to solve it?有谁知道这是否是解决问题的安全方法? Does it always work?它总是有效吗?

It is not safe and does not always work.它不安全并且并不总是有效。

Consider 100,005 • 9.99.考虑 100,005 • 9.99。 In real arithmetic, this is 999,049.95, and you apparently desire to round it to the nearest multiple of 100, producing 999,000.在实际算术中,这是 999,049.95,您显然希望将它四舍五入到最接近的 100 的倍数,得到 999,000。

9.99 cannot be stored in a JavaScript Number. 9.99 不能存储在 JavaScript 号码中。 The nearest representable value is 9.9900000000000002131628207280300557613372802734375.最接近的可表示值是 9.9900000000000002131628207280300557613372802734375。 Multiplying this by 100.005 in JavaScript's floating-point arithmetic yields 999,049.950000000069849193096160888671875.在 JavaScript 的浮点运算中将其乘以 100.005 得到 999,049.950000000069849193096160888671875。

Your proposed solution first attempts to round that to the nearest multiple of 1/10.您提出的解决方案首先尝试将其舍入到最接近的 1/10 的倍数。 In this case, it succeeds, yielding 999,050.在本例中,它成功了,产生了 999,050。 (In many cases, this fails, since the only multiples of 1/10 that can be represented are those that are multiples of 5/10.) Then using Math.round(999050 / 100) * 100) yields 999,100 (since Math.round rounds halfway cases upward). (在许多情况下,这会失败,因为唯一可以表示的 1/10 的倍数是 5/10 的倍数。)然后使用Math.round(999050 / 100) * 100)得到 999,100(因为Math.round中途情况向上)。

Even if real arithmetic were used, rather than floating-point arithmetic, your proposed solution would not work.即使使用真正的算术而不是浮点算术,您提出的解决方案也不会奏效。 Rounding 999,049.95 to the nearest multiple of 1/10 using the same method (halfway cases up) yields 999,050, and rounding that to the nearest multiple of 100 yields 999,100.使用相同的方法(一半的情况)将 999,049.95 舍入到最接近的 1/10 的倍数得到 999,050,并将其舍入到最接近的 100 的倍数得到 999,100。

Rounding to the nearest integer can be simply done by calling四舍五入到最接近的 integer 可以简单地通过调用

Math.round(500249.99999999994)

So rounding to the nearest hundred becomes:因此四舍五入到最接近的百位变为:

 const num = 115000*4.35; const roundedToNearestHundred = Math.round(Math.round(num) / 100) * 100; console.log(roundedToNearestHundred);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM