【C語言】求一個數的二進位制位模式從左到右翻轉後對應的十進位制值。
用函式unsigned int reverse_bit(unsigned int value)實現想要的功能
value是我們想要求的值。
#include <stdio.h>
#include <math.h>
unsigned int reverse_bit(unsigned int value)
{
int sum= 0;
int n = 31;
for(;value != 0,n != 0; value = value >> 1,n--)
{
if(value & 1)
{
sum += 1 *pow(2,n);
}
}
return sum;
}
int main ()
{
printf("%u\n",reverse_bit(25));
return 0;
}
本題用到數學庫的函式pow,其作用是計算冪,比如pow(2,n)是計算2的n次冪。
大致思路是:一個數–>00000000 00000000 00000000 00011001
當最後一位是1時,我們都將它乘以2的31次方,接著將31減1(冪數減減),並累計每次乘積和;若最後一位是0則只進行冪數減減。
但是如果最後一位是1,那麼每次都需要進行累加和計算,所以,這樣的程式,效率往往還是很差的。上面的程式感覺沒有錯誤,但是當你輸入1時,看看執行結果是不是你想要得到的。所以上面的程式是錯誤的。
針對上面程式,下面提供了另一種解決方案:
#include <stdio.h>
#include <math.h>
unsigned int reverse_bit(unsigned int value)
{
int ret = 0;
int one = 0;
int i = 0;
for(i=0; i<32; i++)
{
one = value & 1;
ret = ret | one;
ret <<= 1;
value = value >> 1 ;
}
return ret;
}
int main ()
{
printf("%u\n",reverse_bit(25));
return 0;
}
這個程式主要採用了移位運算子,我們來驗證一下結果:
當我們看到執行結果中的25對應二進位制翻轉後的十進位制數並不符合我們的要求時,肯定知道程式寫錯了,但是你知道錯在哪裡嗎?我們不妨把實參改為1,即把主函式改為:
int main ()
{
printf("%u\n",reverse_bit(1));
return 0;
}
讓我們看看結果:
此時你發現如果把1移到最高位,輸出的應該是2147483648,但是為什麼卻是0呢?
那我們再把主函式改成:
int main ()
{
printf("%u\n",reverse_bit(2147483648));
return 0;
}
我們再來看看結果:
此時執行結果為什麼不是1而是2呢?我們發現在32位系統下,本來我們只需要移動31次就能達到把最低位移到最高位上,而程式的for迴圈中也正是移動31次。當進入執行for迴圈時,ret是在執行完一次操作後才開始左移,所以無形當中已經增加了一次左移操作。那好,既然執行結果不正確,是因為ret多移動了一位,那麼我們就試著把for迴圈中的32改成31,也就是:
for(i=0; i<31; i++)
{
one = value & 1;
ret = ret | one;
ret <<= 1;
value = value >> 1;
}
主函式中的輸出我們依然用:
printf("%u\n",reverse_bit(1));
緊接著我們驗證一下結果:
結果對了!那麼程式就對了!
那麼我們試著把主函式改為:
int main ()
{
printf("%u\n",reverse_bit(2147483648));
return 0;
}
我們再來驗證一下結果
為什麼結果依然不是1呢?我們換個角度思考,既然ret是在第一次操作後多移動了一次,那麼我們可不可以在ret執行第一次操作之前先移動一位,而ret初始化為0,所以既然一共要移動31位,又不影響執行結果,那麼我們可以改變一下for迴圈中語句的執行順序
我們看看正確的程式:
#include <stdio.h>
#include <math.h>
unsigned int reverse_bit(unsigned int value)
{
int ret = 0;
int one = 0;
int i = 0;
for(i=0; i<32; i++)
{
ret <<= 1;
one = value & 1;
ret = ret | one;
value = value >> 1;
}
return ret;
}
int main ()
{
printf("%u\n",reverse_bit(1));
return 0;
}
此時再去驗證執行結果是否正確的工作就留給你們啦~~~~