C++和Python的取模的区别

怎么不一样啊?

现象

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 + ra 为被除数,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$。

Built with Hugo
主题 StackJimmy 设计