C和Python中的取模(%)操作行为不同
我发现同样的取模操作在不同的编程语言中会产生不同的结果。
在Python中:
-1 % 10
结果是9
而在C语言中,结果是-1!
- 那么,哪个才是正确的取模结果呢?
- 如何让C语言中的取模操作和Python中的一样呢?
6 个回答
18
在C89/90版本中,除法运算符和余数运算符在处理负数时的表现是由实现决定的,这意味着不同的编程环境可能会有不同的结果。只要这两个运算符的结果能相互一致就可以了:从a / b = q
和a % b = r
可以推导出a = b * q + r
。如果你的代码依赖于这些运算的结果,建议使用静态断言来检查它们的行为。
到了C99版本,这些运算的行为已经变成了标准。
实际上,这两种行为都有其合理性。Python的行为实现了真正的取模运算。而你在C中观察到的行为则是向0取整的方式(这也是Fortran的行为)。
在C语言中,选择向0取整的原因之一是,这样的结果比较符合直觉。比如,-a / b
的结果应该和-(a / b)
是一样的。如果采用真正的取模行为,-1 % 10
的结果会是9,这样-1 / 10
就得是-1。这可能会让人觉得不太自然,因为-(1 / 10)
的结果是0。
40
Python有一个“真正的”取模操作,而C语言则有一个余数操作。
这两者的区别主要体现在负数除法的处理上,也就是结果是向0取整还是向负无穷取整。Python是向负无穷取整,而C语言则是向0取整。不过在这两种语言中,(n/m)*m + n%m == n
这个关系是成立的,所以取模操作符必须在正确的方向上进行调整。
Ada语言则更明确,它同时有mod
和rem
这两种操作。
90
- 这两种写法都是对的,不过在数学,特别是数论中,Python的取模运算是最常用的。
- 在C语言中,你可以用
((n % M) + M) % M
来得到和Python一样的结果。例如((-1 % 10) + 10) % 10
。注意,这个方法对正整数也有效:((17 % 10) + 10) % 10 == 17 % 10
,而且对于C语言的两种实现(无论是正余数还是负余数)都适用。