模组不能归零吗?

问题描述 投票:0回答:10

为什么

X % 0
是无效表达式?

我一直认为

X % 0
应该等于X。既然你不能除以零,答案自然不应该是余数X(剩下的一切)吗?

c++ modulo divide-by-zero
10个回答
49
投票

C++ 标准(2003)在 §5.6/4 中说,

[...] 如果 / 或 % 的第二个操作数为零,则行为为 未定义; [...]

也就是说,以下表达式调用未定义行为(UB):

X / 0; //UB
X % 0; //UB

还要注意,

-5 % 2
不等于
-(5 % 2)
(正如Petar似乎在他对答案的评论中所暗示的那样)。 它是实现定义的。规范说(§5.6/4),

[...] 如果两个操作数均为非负,则余数为非负; 如果不是,则余数的符号是实现定义的


14
投票

这个答案不适合数学家。这个答案试图给出动力(以数学精度为代价)。

数学家:看这里。

程序员: 请记住,除以

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

4
投票

X % D
定义 是一个数字
0 <= R < D
,因此存在
Q
,因此

X = D*Q + R

因此,如果

D = 0
,则不存在这样的数字(因为
0 <= R < 0


2
投票

我认为因为要获得

X % 0
的余数,您需要首先计算
X / 0
,从而产生无穷大,并且尝试计算无穷大的余数实际上是不可能的。

但是,符合您想法的最佳解决方案是这样做

REMAIN = Y ? X % Y : X

1
投票

另一种在概念上可能容易理解问题的方法:

暂时忽略参数符号的问题,

a % b
可以很容易地重写为
a - ((a / b) * b)
。如果
a / b
为零,则表达式
b
未定义,因此在这种情况下,整个表达式也必须是未定义的。

最后,模数实际上是一种除法运算,因此如果

a / b
未定义,则期望
a % b
也未定义也不是没有道理的。


1
投票

X % Y
给出整数
[ 0, Y )
范围内的结果。
X % 0
必须给出大于或等于零且小于零的结果。


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 处是否连续的问题不同于它是否应该有一个无论如何都有价值。

这里唯一正确的答案是“因为标准是这么说的”。


-1
投票

您可以避免 (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] == 跷跷板曲线的最大值(永远不会达到)== 跷跷板函数的一阶导数

https://www.shadertoy.com/view/MslfW8


-1
投票

我想因为要获得 X % 0 的余数,您需要首先计算 X / 0,从而产生无穷大,并且尝试计算无穷大的余数实际上是不可能的。

但是,符合您想法的最佳解决方案是这样做,

ans = Y ? X % Y : X

此外,在 C++ 文档中,X % 0 或 X / 0 会导致未定义的值。


-1
投票

计算机如何划分:

从被除数开始,减去除数,直到结果小于除数。 减去的次数就是结果,剩下的就是余数。 例如,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
)。

© www.soinside.com 2019 - 2024. All rights reserved.