不能修改零?

Can't Mod Zero?

本文关键字:修改 不能      更新时间:2023-10-16

为什么X % 0是无效表达式?

我一直认为X % 0应该等于X。既然你不能除以0,那么答案自然不应该是余数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


表示XD正除法;它由整数部分和小数部分组成:

(X / D) =   integer    +  fraction
        = floor(X / D) + (X % D) / D

重新排列,得到:

(X % D) = D * (X / D) - D * floor(X / D)

D替换0:

(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)。如果表达式b为零,则表达式a / b是未定义的,因此在这种情况下,整个表达式必须也是。

最后,模数实际上是一个分裂运算,所以如果a / b没有定义,期望a % b也没有定义也不是不合理的。

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

您可以避免(A%B)的类型float identity mod(A, B) for float(B)= B =0.0的"除0"情况,这是未定义的,或者在任何两个实现之间定义不同,以避免逻辑错误(硬崩溃)而有利于算术错误…

通过计算mod([a*b],[b])==b*(a-floor(a))

INSTREAD的
计算mod([a],[b])

其中[a*b]== x轴,随时间变化[b] ==跷跷板曲线的最大值(永远不会达到)==跷跷板函数的一阶导数

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

我想是因为要得到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,则返回NaNInfinity(取决于您的平台)。

这将永远不会结束,所以剩余部分是未定义的(计算机的NaN)。