前天小王同学正在leetcode兴致勃勃的刷题,用java写了一版后又习惯性的用python写了一版,代码逻辑完全一样,但提交答案后居然提示【解答错误】!
经过反复调试,发现问题出在涉及求余的地方,python和java得出的结果居然不一样?!
举个栗子
java的整除与求余
7/4 = 1
-7/4 = -1
7/-4 = -1
-7/-4 = 1
7%4 = 3
-7%4 = -3
7%-4 = 3
-7%-4 = -3
python3下的整除与求余
7//4 = 1
-7//4 = -2
7//-4 = -2
-7//-4 = 1
7%4 = 3
-7%4 = 1
7%-4 = -1
-7%-4 = -3
惊不惊喜,意不意外?
推理
我们用简单的数学语言来描述下:
对于整型数a,b来说,取模运算或者求余运算的方法都是:
求整数商: c = a/b;
计算模或者余数: r = a - c*b
但是求模运算和求余运算在第一步不同,取余运算在取c的值时,向0 方向舍入,而取模运算在计算c的值时,向负无穷方向舍入。
那么借助该知识点我们来再次推演下文章开头的例子
计算-7 Mod 4
那么:a = -7;b = 4;
第一步:求整数商c,c应该是-1.75,如进行求模运算c = -2(向负无穷方向舍入),求余运算则c = -1(向0方向舍入);
第二步:计算模和余数的公式相同,但因c的值不同,求模时r = 1,求余时r = -3。
结论
根据例子及推理。得出如下总结:
- 当a和b符号一致时,求模运算和求余运算所得的c的值一致,因此结果一致。
2. 当符号不一致时,结果不一样。求模运算结果的符号和b一致,求余运算结果的符号和a一致。
经过测试,在C/C++, C#, JAVA, PHP这几门主流语言中,%运算符都是做取余运算,而在python中的%是做取模运算。
扩展:维基百科的相关解释
维基百科-模除zh.wikipedia.org编程语言中,取余和取模的区别到底是什么?www.zhihu.comleetcode实例
整数反转 - 力扣(LeetCode)leetcode-cn.com下面附上两个语言版本的代码实例,大家可以亲身体会下,当除数与被除数符号不一致时一定多多加小心:
Java版
class Solution {public int reverse(int x) {int rev = 0;while (x != 0) {int pop = x % 10;x /= 10;if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;rev = rev * 10 + pop;}return rev;}
}
Python版
class Solution:def reverse(self, x: int) -> int:INT_MAX = pow(2,31) - 1INT_MIN = - pow(2,31)rev = 0while x!=0:if x > 0:pop = x%10x = x//10else:pop = x%-10x = -(x//-10)if rev > INT_MAX/10 or (rev== INT_MAX//10 and pop > 7):return 0if rev < INT_MIN/10 or (rev == INT_MIN//10 and pop < -8):return 0rev = rev*10 + pop return rev