为什么
X % 0
是无效表达式?
我一直认为
X % 0
应该等于X。既然你不能除以零,答案自然不应该是余数X(剩下的一切)吗?
C++ 标准(2003)在 §5.6/4 中说,
[...] 如果 / 或 % 的第二个操作数为零,则行为为 未定义; [...]
也就是说,以下表达式调用未定义行为(UB):
X / 0; //UB
X % 0; //UB
还要注意,
-5 % 2
不等于-(5 % 2)
(正如Petar似乎在他对答案的评论中所暗示的那样)。 它是实现定义的。规范说(§5.6/4),
[...] 如果两个操作数均为非负,则余数为非负; 如果不是,则余数的符号是实现定义的。
这个答案不适合数学家。这个答案试图给出动力(以数学精度为代价)。
数学家:看这里。
程序员: 请记住,除以
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
)
我认为因为要获得
X % 0
的余数,您需要首先计算 X / 0
,从而产生无穷大,并且尝试计算无穷大的余数实际上是不可能的。
但是,符合您想法的最佳解决方案是这样做
REMAIN = Y ? X % Y : X
另一种在概念上可能容易理解问题的方法:
暂时忽略参数符号的问题,
a % b
可以很容易地重写为a - ((a / b) * b)
。如果 a / b
为零,则表达式 b
未定义,因此在这种情况下,整个表达式也必须是未定义的。
最后,模数实际上是一种除法运算,因此如果
a / b
未定义,则期望 a % b
也未定义也不是没有道理的。
X % Y
给出整数 [ 0, Y )
范围内的结果。 X % 0
必须给出大于或等于零且小于零的结果。
呃...我认为这里的数学合理化有点不确定,因为 |x mod y| <= |y| and it therefore makes perfect sense to use the squeeze theorem to ‘patch it up’ by defining x mod 0 = 0.
确实,在接近 y = 0 时,您会遇到越来越多的不连续性,实际上是无限多,但它们会变得越来越小,并且在 y = 0 处是否连续的问题不同于它是否应该有一个无论如何都有价值。
这里唯一正确的答案是“因为标准是这么说的”。
您可以避免 (A%B) 类型的“被 0 除”的情况,对于 float(B)=b=0.0 ,其类型为 float 恒等 mod(a,b) ,即未定义,或在任何 2 个实现之间定义不同,避免逻辑错误(硬崩溃)而有利于算术错误......
通过计算
mod([a*b],[b])==b*(a-floor(a))
mod([a],[b])
其中 [a*b]==你的 x 轴,随着时间的推移 [b] == 跷跷板曲线的最大值(永远不会达到)== 跷跷板函数的一阶导数
我想因为要获得 X % 0 的余数,您需要首先计算 X / 0,从而产生无穷大,并且尝试计算无穷大的余数实际上是不可能的。
但是,符合您想法的最佳解决方案是这样做,
ans = Y ? X % Y : X
此外,在 C++ 文档中,X % 0 或 X / 0 会导致未定义的值。
计算机如何划分:
从被除数开始,减去除数,直到结果小于除数。 减去的次数就是结果,剩下的就是余数。 例如,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
)。