今天發現一個很有意思的現象。
當做除法的時候,Python2和C++在負數的情況下會得到不同的整除結果:
當做-5 / 3的時候
C++的結果: -1
Python2的結果:-2
(請注意5 / -3的時候仍然會在C++中得到-1, Python2中得到-2)
可以看出C++在進行負數整除的時候執行的是直接舍去小數點后數字的操作,也就是返回和0比較接近的那個數字。
但在Python2中返回的則是小於等於商的最大整數,也就是返回和-∞更接近的數。
在做%操作的時候,依據的是這樣的邏輯:
a = b * c + r
其中a是被除數,b是除數,c是商,r是%操作的結果。
在上述例子中,a和b是-5和3。
C++的情況下商c是-1,因此r可以算出來是-2。
Python情況下商c是-2,因此r可以算出來是1。
!!!值得注意的是:當把操作改成5 % -3的時候,C++的結果是2,Python2的結果是-1,和之前的結果正好符號相反。
如果有同學覺得這里非常亂,請牢記a = b * c + r。
用同樣的邏輯,當a是5,b是-3時,c++因為商c是-1,因此r是2,Python時商c是-2因此r是-1。
那么造成這種差異的原因是什么呢?
其實是因為“求模”(Modulus)和“取余”(Remainder)的區別。
很多同學可能認為,求模運算和取余運算是一回事。實際上在正整數范圍內它們確實表現出完全相同的性質。但在負數運算的情況下,它們則會表現出不同的行為。
C++的%表現出的是“取余”操作的結果。
Python的%表現出的是“求模”操作的結果。
無論C++還是Python,求模和取余都是根據a = b * c + r這個公式定義的,而唯一的區別就是商c究竟是向0方向取整還是向-∞方向取整。
當商c向0方向取整的時候,得到的r是“余數”,也就是在C++中的結果。
當商c向-∞方向取整的時候,得到的r是“模數”,也就是在Python2中的結果。
在Python3中,無論“/”兩邊是否均為整數,運算的時候都轉換成實數運算並返回實數。整除則用“//”來表示。
利用Python這個整除的特性,我們可以得到一個小技巧:
很多時候我們會碰到“某物x個一組,一共需要y個,至少需要多少組?”這樣的問題。
在C++中我們必須寫成這樣的邏輯:answer = y / x; if (y % x != 0) ans += 1;
在Python中我們可以利用負數的特性很方便地得到結果:answer = -(-y // x)。