踩坑之路--負數取模、取模與取餘
阿新 • • 發佈:2021-12-12
兩種判斷奇偶的方式
正常判斷一個數為奇數還是偶數的常見思路便是通過對2取模進行判斷,比如通過x%2!=0
和x%2==1
判斷是否為奇數。但這兩種方法真的都不會出錯嗎?下面用一段簡單的程式碼測試下:
#include <bits/stdc++.h> using namespace std; int main() { while (1) { int n; cin >> n; cout << "n: " << n << endl; cout << "n % 2 != 0 : "; if (n % 2 != 0) { cout << "奇數" << endl; } else { cout << "偶數" << endl; } cout << "n % 2 == 1 : "; if (n % 2 == 1) { cout << "奇數" << endl; } else { cout << "偶數" << endl; } cout << endl << endl; } }
最終結果如下:
n: 3
n % 2 != 0 : 奇數
n % 2 == 1 : 奇數
n: 4
n % 2 != 0 : 偶數
n % 2 == 1 : 偶數
n: -3
n % 2 != 0 : 奇數
n % 2 == 1 : 偶數
n: -4
n % 2 != 0 : 偶數
n % 2 == 1 : 偶數
可以看出此時用x%2==1
判斷出錯,難道負數取模和正數取模有什麼不同?下面簡要分析一下。
負數取模
通過C++(gcc 8.1.0)編寫一段程式碼可以測試出如下結果
4 % 3 = 1
4 % -3 = 1
-4 % 3 = -1
-4 % -3 = -1
而用python 3.6.1 測試結果如下
>>> 4 % 3
1
>>> 4 % -3
-2
>>> -4 % 3
2
>>> -4 % -3
-1
用windows自帶計算機計算結果如下
4 % 3 = 1
4 % -3 = 1
-4 % 3 = -1
-4 % -3 = -1
通過查資料可知這裡的主要區別原因是取整方式的選擇(具體可見維基百科 中的定義)。C++採用的是向零取整,而python採用的是向下取整,因此導致了餘數的歧義進而導致了模數的不同。
取模與取餘
取模運算(“Modulo Operation”)和取餘運算(“Remainder Operation ”)兩個概念有重疊的部分但又不完全一致。主要的區別在於對負整數進行除法運算時操作不同。取模主要是用於計算機術語中。取餘則更多是數學概念。
-
取餘,遵循儘可能讓商向0靠近的原則(即上文C++向零取整)
-
取模,遵循儘可能讓商向負無窮靠近的原則(即上文python向負無窮取整)
針對x%y的結果,當 x 和 y 的正負號一樣的時候,兩種運算結果是等同的;當 x 和 y 的符號不同時,取餘結果的符號和 x 的一樣,而 取模 和 y 一樣。所以可以看出C++中的%
嚴格上應該稱為取餘運算而不是取模運算。
所以通過上文中可以看出利用x%2==1
判斷數字的奇偶性是會出錯的,那麼除了x%2!=0
還有別的方式嗎?答案就是x&1
,詳細可見位運算總結。
參考連結