不能调零吗?

发布于 2024-12-04 01:37:39 字数 109 浏览 1 评论 0原文

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

我一直认为 X % 0 应该等于 X。既然不能除以零,答案自然不应该是余数 X(剩下的所有内容)吗?

Why is X % 0 an invalid expression?

I always thought X % 0 should equal X. Since you can't divide by zero, shouldn't the answer naturally be the remainder, X (everything left over)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

深居我梦 2024-12-11 01:37:39

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

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

也就是说,以下表达式调用 undefined-behavior(UB):

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

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

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

The C++ Standard(2003) says in §5.6/4,

[...] If the second operand of / or % is zero the behavior is undefined; [...]

That is, following expressions invoke undefined-behavior(UB):

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

Note also that -5 % 2 is NOT equal to -(5 % 2) (as Petar seems to suggest in his comment to his answer). It's implementation-defined. The spec says (§5.6/4),

[...] If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined.

我们的影子 2024-12-11 01:37:39

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

数学家: 请参阅此处。

程序员:请记住,除以0未定义。因此,依赖于除法的mod也是未定义


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

(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未定义:

(X % 0) = 0 * undefined - 0 * floor(undefined)
        = undefined - undefined
        = undefined

This answer is not for the mathematician. This answer attempts to give motivation (at the cost of mathematical precision).

Mathematicians: See here.

Programmers: Remember that division by 0 is undefined. Therefore, mod, which relies on division, is also undefined.


This represents division for positive X and D; it's made up of the integral part and fractional part:

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

Rearranging, you get:

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

Substituting 0 for D:

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

Since division by 0 is undefined:

(X % 0) = 0 * undefined - 0 * floor(undefined)
        = undefined - undefined
        = undefined
别忘他 2024-12-11 01:37:39

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

X = D*Q + R

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

X % D is by definition a number 0 <= R < D, such that there exists Q so that

X = D*Q + R

So if D = 0, no such number can exists (because 0 <= R < 0)

本王不退位尔等都是臣 2024-12-11 01:37:39

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

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

REMAIN = Y ? X % Y : X

I think because to get the remainder of X % 0 you need to first calculate X / 0 which yields infinity, and trying to calculate the remainder of infinity is not really possible.

However, the best solution in line with your thinking would be to do something like this

REMAIN = Y ? X % Y : X
我最亲爱的 2024-12-11 01:37:39

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

暂时忽略参数符号的问题,a % b 可以轻松地重写为 a - ((a / b) * b)。如果 b 为零,则表达式 a / b 未定义,因此在这种情况下整个表达式也必须是未定义的。

最后,模数实际上是一个除法运算,因此如果 a / b 未定义,则期望 a % b 也是如此也不是没有道理的。

Another way that might be conceptually easy to understand the issue:

Ignoring for the moment the issue of argument sign, a % b could easily be re-written as a - ((a / b) * b). The expression a / b is undefined if b is zero, so in that case the overall expression must be too.

In the end, modulus is effectively a divisive operation, so if a / b is undefined, it's not unreasonable to expect a % b to be as well.

标点 2024-12-11 01:37:39

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

X % Y gives a result in the integer [ 0, Y ) range. X % 0 would have to give a result greater or equal to zero, and less than zero.

游魂 2024-12-11 01:37:39

呃...我认为这里的数学合理化有点不确定,因为 |x mod y| <= |y|因此,使用挤压定理通过定义 x mod 0 = 0 来“修补它”是非常有意义的。

确实,在接近 y = 0 时,您会遇到越来越多的不连续性,实际上是无限多,但是它们变得越来越小,并且它在 y = 0 处是否连续的问题与它是否应该在 y = 0 处具有值的问题不同。

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

Erm... I think the mathematical rationalisations here are a bit iffy given that |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.

It's true that on your approach to y = 0 you'll encounter more and more discontinuities, infinitely many in fact, but they get smaller and smaller and the question of whether it's continuous at y = 0 is different from whether it should have a value there anyway.

The only true answer here is ‘because the standard says so’.

美男兮 2024-12-11 01:37:39

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

通过计算 mod([a*b],[b])==b*(a-floor(a))
代替
随着时间的推移,计算 mod([a],[b])

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

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

you can evade the "divivion by 0" case of (A%B) for its type float identity mod(a,b) for float(B)=b=0.0 , that is undefined, or defined differently between any 2 implementations, to avoid logic errors (hard crashes) in favor of arithmetic errors...

by computing mod([a*b],[b])==b*(a-floor(a))
INSTREAD OF
computing mod([a],[b])

where [a*b]==your x-axis, over time
[b] == the maximum of the seesaw curve (that will never be reached) == the first derivative of the seesaw function

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

此岸叶落 2024-12-11 01:37:39

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

但是,符合您想法的最佳解决方案是执行类似的操作,

ans = Y ? X % Y : X

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

I suppose because to get the remainder of X % 0 you need to first calculate X / 0 which yields infinity, and trying to calculate the remainder of infinity is not really possible.

However, the best solution in line with your thinking would be to do something like this,

ans = Y ? X % Y : X

Also, in C++ docs its written that X % 0 or X / 0 ,results in an undefined value.

静若繁花 2024-12-11 01:37:39

计算机如何除法:

从被除数开始,减去除数,直到结果小于除数。减去的次数就是结果,剩下的就是余数。例如,要除 10 和 3:

10 - 3 = 7
7 - 3 = 4
4 - 3 = 1

So

10 / 3 = 3
10 % 3 = 1

要除 1 和 0:

1 / 0
1 - 0 = 1  
1 - 0 = 1  
1 - 0 = 1  
...

So

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)。

How computers divide:

Start with the dividend and subtract the divisor until the result is less then the divisor. The number of times you subtracted is the result and what you have left is the remainder. For example, to divide 10 and 3:

10 - 3 = 7
7 - 3 = 4
4 - 3 = 1

So

10 / 3 = 3
10 % 3 = 1

To divide 1 and 0:

1 / 0
1 - 0 = 1  
1 - 0 = 1  
1 - 0 = 1  
...

So

1 / 0 = Infinity (technically even infinity is too small, but it's easy to classify it as that)
1 % 0 = NaN

If there is nothing to stop it, the CPU will continue to execute this until it overloads and returns a totally random result. So there is an instruction at the CPU level that if the divisor is 0, return NaN or Infinity (depending on your platform).

This will never end so the remainder is undefined (which is NaN for computers).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文