JavaScript中使用取模(%)运算符的正确方式是什么?

3

在JavaScript中,%运算符似乎表现得非常奇怪。我尝试了以下内容:

>>> (0 - 11) % 12
-11

为什么返回-11而不是1(与Python的结果不同)?我确定我做错了或期望错了,但文档没有告诉我是哪里出了问题。
5个回答

7
根据语言规范(例如ECMA 262),它的行为是正确的,它被称为余数运算符而不是模运算符。从规范中可以看出:
ECMAScript浮点余数运算的结果由IEEE算术规则确定: - 如果任一操作数为NaN,则结果为NaN。 - 结果的符号等于被除数的符号。 - 如果被除数是无穷大,或者除数是零,或者两者都是,则结果为NaN。 - 如果被除数是有限的且除数是无穷大,则结果等于被除数。 - 如果被除数是零且除数是非零且有限的,则结果与被除数相同。 - 在剩下的情况下,既没有无穷大也没有零也没有NaN涉及,从被除数n和除数d中得到的浮点余数r由数学关系r = n - (d * q)定义,其中q是一个整数,当n/d为负时为负,当n/d为正时为正,并且其数量级尽可能大而不超过n和d的真实数学商的数量级。使用IEEE 754舍入到最近可表示值的模式计算和四舍五入r。
在你的情况下,n/d是负数,因此结果也是负数。 请参阅维基百科关于模运算的条目以获取更多详细信息,包括按结果符号进行分类的语言列表。

1

有两个类似的操作:模运算和余数运算。模运算表示更数学化的用法,而余数运算则更多地用于IT。

假设我们有两个整数a和b。

MOD(a,b)将返回与b相同符号的结果。

REM(a,b)将返回与a相同符号的结果。 - 这是在C / C ++ / C#中实现为%运算符并经常令人困惑地称为“mod”的内容

您也可以这样想:

MOD(a,b)将找到小于a的最大整数倍数b(称为“c”),并返回(a-c)。

例如MOD(-340,60),我们发现c = -360是小于-340的最大60的倍数。因此,我们得到(-340-(-360))= 20。

REM(a,b)将返回一个值,使得(DIV(a,b)* b)+ REM(a,b)= a,其中DIV()表示整数除法。

因此,对于r = REM(-340,60)

-340 = DIV(-340,60)* 60 + r = -5 * 60 + r = r-300

这将解决问题,使得 r = -40。


0

-11 < 12,所以我“猜测”它们实际上并没有被除尽: 因此,-11 = 0x12 -11

试试看 (0-13) % 12


0
你说MOD(a,b)会返回与b相同符号的结果,但又说它返回(a-c),其中c小于a。这第二个定义意味着它总是返回一个正数。那么它到底是哪一个?

-1

Python中的math模块中的fmod函数表现正常:

>>> from math import *
>>> fmod(-11, 12)
-11.0

-11 是正确答案。


1
“正确”取决于你如何定义模数。我怀疑 JavaScript 实现也符合他们的定义。请查看我的回答中的链接 - 这个问题并不像你想象的那么清晰。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接