2009 12 22 16 42 [程式] 如何判斷某個數字是否是2的n次方,

因為最近需要用到判斷某個數字是否是2的n次方,

這個方法應該是我在某本書上讀到的,

不過我手上應該是沒有哪本書。

方法其實是很簡單的,

某個數字是 X,

先將 X - 1 ,

再把 X ^ ( X - 1) 跟 X 比,

如果, X ^ ( X - 1 ) >= X,

就代表這個數字是2的n次方。

理由是因為,

假設 X = 1000000 (二進位),

那麼 X - 1 = 0111111 (二進位),

再來是 X ^ ( X - 1) = 1111111 ,

這個數字會大於等於原來的 X 。

而這是因為這個數字是2的n次方。

 

如果這個數字不是2的n次方,

假如 X = 1000100 ( 二進位)

而 X - 1 = 1000011 (二進位)

會讓 X ^ ( X - 1 ) = 111 (二進位)

最後的數字會小於 X 。

原因是在於最左邊的 1 ,

假如是2的n次方,整個數字(二進位)應該只會有一個1,

而不是2的n次方的話,就不只有一個1,

如果不是的話,這個會讓後面要做的 - 1 ,

在減掉 1 之後,最左邊的1還是不會改變。

因為最左邊的1還是存在,又跟原來的數字做 XOR ,

XOR 出來的結果,就會比原來的小。

這也是為什麼可以這樣判斷。

但是『等號』是只會成立在,當 X == 1 時。

 

而比較特別的是,當 X == 0 時,也是會成立的。

這可以當成是因為溢位的關係。

如果不想要這個特性的話,可以先檢查是否為0。

 

以下程式是用來驗證整個設計是否正確,

只有在條件(是否是2的n次方)成立時,才把 i 列印出來。

#include <stdio.h>

int main()
{
unsigned int i = 0;
for (i = 0;; i++) {
if ((i ^ (i - 1)) >= i) {
printf("%08x\n", i);
}
if (i == 0xffffffff) {
break;
}
}
return 0;
}