为什么在JavaScript中取模运算符返回小数?

10 浏览
0 Comments

为什么在JavaScript中取模运算符返回小数?

为什么在JavaScript中, 49.90 % 0.10 返回 0.09999999999999581?我预期应该是0。

0
0 Comments

JavaScript中的模运算符会返回小数的原因是,JavaScript的Number类型使用的是“IEEE双精度”来存储数值,无法精确存储所有的小数。当将小数转换为二进制时,会产生舍入误差,因此结果不为零。

49.90 = 49.89999999999999857891452848...
 0.10 =  0.10000000000000000555111512...

因此,floor(49.90 / 0.10)只等于498,余数将为0.09999....


看起来你正在使用数字来存储美元金额。不要这样做,因为浮点数运算会传播和放大舍入误差。相反,应该将金额以"分"的形式存储。整数可以被准确表示,4990 % 10将返回0。

0
0 Comments

在JavaScript中,模运算符(%)返回一个浮点数的原因是因为JavaScript没有内置的模运算符。为了解决这个问题,可以使用下面这个函数来更精确地处理浮点数的余数:

function floatSafeRemainder(val, step){
  var valDecCount = (val.toString().split('.')[1] || '').length;
  var stepDecCount = (step.toString().split('.')[1] || '').length;
  var decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
  var valInt = parseInt(val.toFixed(decCount).replace('.',''));
  var stepInt = parseInt(step.toFixed(decCount).replace('.',''));
  return (valInt % stepInt) / Math.pow(10, decCount);
}

如果你关心负数的情况,JavaScript的模运算符处理负数的方式可能与你期望的不同。你可以将返回语句修改为:

return (((valInt % stepInt) + stepInt) % stepInt) / Math.pow(10, decCount);

这个函数虽然有点冗长,但是非常健壮。如果你花时间阅读一下,会发现它的工作非常出色。

0
0 Comments

JavaScript中的模运算符返回小数的原因是因为JavaScript使用浮点数运算,这可能会导致舍入误差。如果您需要精确到两位小数的结果,在进行运算之前,将数字乘以100,然后再进行除法运算:

var result = ( 4990 % 10 ) / 100;

如果需要的话进行舍入。在许多金融系统中,这是处理货币的内部方式(乘以100),在渲染时应用货币规则。

哇,很好的技巧,通过事先将数字转换为整数来避免浮点数。太简单了。

这也被称为“固定点算术”,因为您总是有2(或N)个小数位。

感谢您的见解,但这种方法并不完美。 (40.55 * 100 %1000)/100 的结果是0.549999... 而不是0.55。

答案中提到了“必要时进行舍入”,我会补充一点,如果需要的话,在输出上使用toFixed(2)来进行舍入。toFixed已经进行了四舍五入。

0