不能调零吗?
为什么 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
C++ 标准(2003)在 §5.6/4 中说,
也就是说,以下表达式调用 undefined-behavior(UB):
另请注意
-5 % 2
不等于-(5 % 2)
(正如佩塔尔似乎在他对他的回答的评论中所暗示的那样)。它是实现定义的。规范说(§5.6/4),The C++ Standard(2003) says in §5.6/4,
That is, following expressions invoke undefined-behavior(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),这个答案不适合数学家。这个答案试图给出动机(以数学精度为代价)。
数学家: 请参阅此处。
程序员:请记住,除以
0
是未定义
。因此,依赖于除法的mod
也是未定义
。这表示正
X
和D
的除法;它由整数部分和小数部分组成:重新排列,得到:
将
0
替换为D
:因为除以
0
是未定义:
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
isundefined
. Therefore,mod
, which relies on division, is alsoundefined
.This represents division for positive
X
andD
; it's made up of the integral part and fractional part:Rearranging, you get:
Substituting
0
forD
:Since division by
0
isundefined
:X % D
根据定义是一个数字0 <= R < D
,因此存在Q
,因此如果
D = 0
,则不存在这样的数字(因为0 <= R <
0 <= R
) 0
)X % D
is by definition a number0 <= R < D
, such that there existsQ
so thatSo if
D = 0
, no such number can exists (because0 <= R < 0
)我认为因为要获得
X % 0
的余数,您需要首先计算X / 0
,从而产生无穷大,并且尝试计算无穷大的余数实际上是不可能的。但是,符合您想法的最佳解决方案是这样做
I think because to get the remainder of
X % 0
you need to first calculateX / 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
另一种在概念上可能很容易理解该问题的方法:
暂时忽略参数符号的问题,
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 asa - ((a / b) * b)
. The expressiona / b
is undefined ifb
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 expecta % b
to be as well.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.呃...我认为这里的数学合理化有点不确定,因为 |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’.
您可以避免 (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
我想因为要获得 X % 0 的余数,您需要首先计算 X / 0 ,从而产生无穷大,并且尝试计算无穷大的余数实际上是不可能的。
但是,符合您想法的最佳解决方案是执行类似的操作,
此外,在 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,
Also, in C++ docs its written that X % 0 or X / 0 ,results in an undefined value.
计算机如何除法:
从被除数开始,减去除数,直到结果小于除数。减去的次数就是结果,剩下的就是余数。例如,要除 10 和 3:
So
要除 1 和 0:
So
如果没有什么可以阻止它,CPU 将继续执行此操作,直到它过载并返回完全随机的结果。所以CPU层面有一条指令,如果除数为0,则返回
NaN
或Infinity
(取决于你的平台)。这永远不会结束,因此余数未定义(对于计算机来说是
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:
So
To divide 1 and 0:
So
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
orInfinity
(depending on your platform).This will never end so the remainder is undefined (which is
NaN
for computers).