为什么是X % 0
无效表达式?
我一直认为X % 0
应该等于X。既然你不能除以零,那么答案自然不应该是余数,X(剩下的一切)吗?
C++ 标准(2003)在 §5.6/4 中说,
[...] 如果 / 或 % 的第二个操作数为零,则行为未定义;[...]
也就是说,以下表达式调用 undefined-behavior(UB):
X / 0; //UB
X % 0; //UB
另请注意,这-5 % 2
不等于-(5 % 2)
(正如 Petar 在他对他的回答的评论中暗示的那样)。它是实现定义的。规范说(§5.6/4),
[...] 如果两个操作数都是非负数,那么余数是非负数;如果不是,则余数的符号是 implementation-defined。
这个答案不适合数学家。这个答案试图提供动力(以数学精度为代价)。
数学家: 看这里。
程序员:记住除以0
是undefined
. 因此,mod
依靠除法的 ,也是undefined
。
这表示正X
和的除法D
;它由整数部分和小数部分组成:
(X / D) = integer + fraction
= floor(X / D) + (X % D) / D
重新排列,你得到:
(X % D) = D * (X / D) - D * floor(X / D)
代替:0
_D
(X % 0) = 0 * (X / 0) - 0 * floor(X / 0)
由于除以0
是undefined
:
(X % 0) = 0 * undefined - 0 * floor(undefined)
= undefined - undefined
= undefined
X % D
根据定义是一个数字0 <= R < D
,这样存在Q
,使得
X = D*Q + R
因此,如果D = 0
,则不存在这样的数字(因为0 <= R < 0
)
另一种在概念上可能易于理解问题的方式:
暂时忽略参数符号的问题,a % b
可以很容易地重写为a - ((a / b) * b)
. 如果为零,则表达式a / b
未定义,因此在这种情况下,整个表达式也必须是。b
最后,模数实际上是一种除法运算,因此如果a / b
未定义,那么期望它也是如此并非不合理a % b
。
我认为因为要获得剩余部分,X % 0
您需要首先计算X / 0
哪个产生无穷大,而尝试计算无穷大的剩余部分实际上是不可能的。
但是,符合您想法的最佳解决方案是做这样的事情
REMAIN = Y ? X % Y : X
X % Y
给出整数[ 0, Y )
范围内的结果. X % 0
必须给出大于或等于零且小于零的结果。
我想因为要获得 X % 0 的余数,您需要首先计算 X / 0 产生无穷大,而试图计算无穷大的余数实际上是不可能的。
但是,符合您想法的最佳解决方案是做这样的事情,
ans = Y ? X % Y : X
此外,在 C++ 文档中,它写道 X % 0 或 X / 0 会导致未定义的值。
您可以避免 (A%B) 的“除以 0”的情况,因为它的类型 float 标识 mod(a,b) for float(B)=b=0.0 是未定义的,或者在任何两个实现之间定义不同,以避免逻辑错误(硬崩溃)有利于算术错误......
通过计算mod([a*b],[b])==b*(a-floor(a))
INSTREAD OF
计算mod([a],[b])
其中 [a*b]== 你的 x 轴,随着时间的推移 [b] == 跷跷板曲线的最大值(永远不会达到)== 跷跷板函数的一阶导数
计算机如何划分:
从被除数开始减去除数,直到结果小于除数。减去的次数就是结果,剩下的就是余数。例如,除以 10 和 3:
10 - 3 = 7
7 - 3 = 4
4 - 3 = 1
所以
10 / 3 = 3
10 % 3 = 1
将 1 和 0 相除:
1 / 0
1 - 0 = 1
1 - 0 = 1
1 - 0 = 1
...
所以
1 / 0 = Infinity (technically even infinity is too small, but it's easy to classify it as that)
1 % 0 = NaN
如果没有什么可以阻止它,CPU 将继续执行它,直到它过载并返回一个完全随机的结果。因此,在 CPU 级别有一条指令,如果除数为 0,则返回NaN
或Infinity
(取决于您的平台)。
这将永远不会结束,因此其余部分未定义(NaN
用于计算机)。