對於十進制轉二進制,我的初步想法是將32位整數每次左移一位,將移出的那位保存到對應的數組裏,最後控制格式,輸出打印。
第一步:
因爲每次移出的那位都在最高位,爲了獲取它,必須屏蔽其他位,布爾與運算&派上用場了,又考慮是32位整數,temp = digit & (1<<31)便可以判斷最高位是1還是0了。
如果現在立即將它輸出,可能出錯,對於最高位0,這不是問題,可是對於最高位1,二進制結果可能是1000 0000 0000 0000 0000 0000 0000 0000,翻譯成十進制就是一個負數:-2147483648.這不是我想要的,於是我再次右移31位,變成0000 0000 0000 0000 0000 0000 0000 00001.
第二步:
可是沒想到右移運算和最高位有關,對於1000 0000 0000 0000 0000 0000 0000 0000來說,右移31位就變成1111 1111 1111 1111 1111 1111 1111 1111。這又不是我想要的,於是我得將右移結果再屏蔽一次,即: temp = (temp>>31) &1
第三步:
只要十進制不爲0,十進制數左移1位, digit<<=1輸出.這裏結束條件之所以是digit !=0而不是左移32位才結束,是因爲我採用了數組,將其全部32個數據初始化爲0。這樣對於最後一位1右邊的所有0,就不用再判斷了。
源代碼如下:
#include <iostream>
using namespace std;
//十進制轉二進制
void DecToBin(int digit,int bin[])
{
int i=0;
while(digit !=0)
{
int temp =digit & (1<<31); //判斷最高位
temp = (temp>>31)&1; //將最高位右移到最低位,同時屏蔽擴展位.
bin[i++]=temp;
digit<<=1; //整數左移一位,最高位自動丟棄,不能保存
}
}
int main()
{
int a=-10002;
int b[32]={0};
cout<<"a= " <<a<<endl;
DecToBin(a,b);
cout<<"a=";
for(int i=0;i<32;i++)
{
if(i%4==0) //每四位二進制一組
{
cout<<" ";
}
cout<<b[i];
}
cout<<endl;
getchar();
}
結果出來了,但是網上搜羅了下,其實還有更好的想法,如下: #define CHAR_BIT 8
void bit_print(int a)
{
int i;
int n = sizeof(int) * CHAR_BIT;
int mask = 1 << (n - 1);
for(i = 1; i <= n; ++i)
{
putchar(((a & mask) == 0) ? '0' : '1'); //這一步速度上應該更快,不需要每次都移32位
a <<= 1;
if(i % CHAR_BIT == 0 && i < n)
putchar(' ');
}}
以上代碼沒有采用數組,邏輯上更好理解,而且簡化了第二步的判斷;更爲重要的是它是跨平臺的,對不同機器字長都可以勝任。
此外,在保存輸出的二進制結果的問題上,又提出瞭如何使輸出結果佔用內存最小?於是有人用字符串實現,是我的int[ ]數組內存大小的1/4.實現如下:int dtob(int d, char *bstr)
{
if(d<0)
return -1;
int mod =0;
char tmpstr[64];
bzero(tmpstr,sizeof(tmpstr));
bzero(bstr,sizeof(bstr));
int i=0;
while(d>0)
{
mod = d%2;
d/=2;
tmpstr[i] = mod+ '0';
i++;
}
unsigned int len = strlen(tmpstr);
for(i=0; i<len; i++) //複製字符串
{
bstr[i] = tmpstr[len-i-1];
}
return (int) len;
}
不過還是有人感覺上面太羅嗦了,而且爲負數的時候無法工作,於是有如下實現:
void d2b(unsigned int d, char *str)
{
int nStart = -1, i = 0;
for (i=0; i<32; i++)
{
bool bOne = (0 != (d & (1 << (32 - i - 1))));
if (bOne && nStart < 0)
{
nStart = i;
}
str[i - nStart] = bOne ? '1' : '0';
}
str[i - nStart] = '\0';
}
看了以上各種實現,還是有很多在實際編程過程中沒有考慮的問題,列舉如下:
1.如果輸入的整數過大怎麼辦?本着一個函數完成一個功能的模塊化原則,要麼輸出錯誤,直接返回,要麼採用動態數組或鏈表進行處理。
2.傳入的數組不是全部爲0,怎麼辦? 對於我寫的程序就有問題,避免的唯一方法就是每次函數調用的時候將其初始化爲0
3.整數在不同的機器上,機器字長是不一樣的.不考慮這一點,會有很大隱患。第二種方法,很好的屏蔽了這個問題,值得借鑑!
4.數據過大還會遇到另外一個問題,那就是參數聲明的是int類型,如果傳入的參數是long int 或者double怎麼辦?數據過大,會造成多餘的位數丟棄!解決的思路應該是將輸入int參數,改爲void*指針比較好,然後在函數內進行強制轉換
5.對於計算機,即使long double這樣的整數,它的位數也是有限的,位數再多點它也會溢出報錯!如此這樣,除了第1種建議中的鏈表處理,還要對輸入的數字個數進行判斷,非法輸入進行屏蔽。解決的思路就是統計輸入字符的個數,將數字轉化爲數字字符,然後作相應處理.
總之,對於我們程序員來說,考慮的越多越詳細,代碼纔會更加健壯!靈活的頭腦加上辛勤的汗水,纔是成功的必由之路。
本人寫的程序附圖: