现象
1
2
3
4
5
6
7
8
| print(8 % 3)
print(4 % 7)
print(-8 % 3)
print(-4 % 7)
print(8 % -3)
print(4 % -7)
print(-8 % -3)
print(-4 % -7)
|
在 Python
中,运行以上程序的结果是:
1
2
3
4
5
6
7
8
| 2
4
1
3
-1
-3
-2
-4
|
在 C++
中,编写看起来意思一样的程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| #include <iostream>
using namespace std;
int main() {
cout << 8 % 3 << endl;
cout << 4 % 7 << endl;
cout << -8 % 3 << endl;
cout << -4 % 7 << endl;
cout << 8 % -3 << endl;
cout << 4 % -7 << endl;
cout << -8 % -3 << endl;
cout << -4 % -7 << endl;
return 0;
}
|
然而,两个程序的运行结果不一样。下面是 C++
程序的结果。
1
2
3
4
5
6
7
8
| 2
4
-2
-4
2
4
-2
-4
|
分析
整理数据
整理一下数据,列个表格。
算式 | Python 结果 | C++ 结果 |
---|
$8 \bmod 3$ | $2$ | $2$ |
$4 \bmod 7$ | $4$ | $4$ |
$-8 \bmod 3$ | $1$ | $-2$ |
$-4 \bmod 7$ | $3$ | $-4$ |
$8 \bmod -3$ | $-1$ | $2$ |
$4 \bmod -7$ | $-3$ | $4$ |
$-8 \bmod -3$ | $-2$ | $-2$ |
$-4 \bmod -7$ | $-4$ | $-4$ |
原因
两种语言给出不同的结果的原因是这两种语言执行除法的方式不同。(欧几里得除法:a = b * q + r
,a
为被除数,b
为除数,q
为商,r
为余数)
Python
采用的方法是:向负无穷方向舍入,即让商更小(但需保证 $-|b| \le r \le |b|$)。C++
采用的方法是:向零舍入,即让商更靠近零(但需保证 $-|b| \le r \le |b|$)。
举个例子
1
2
3
4
5
| -8 / 3
Python:
-8 = 3 * -3 + 1
C++:
-8 = 3 * -2 - 2
|
1
2
3
4
5
| 4 / -7
Python:
4 = -7 * -1 - 3
C++:
4 = -7 * 0 + 4
|
拓展
如何让余数变为非负整数
保证余数为非负整数只需 $((a \bmod b) + b) \bmod b$。