一文攻破BCD碼轉換與各進位轉換
- 2019 年 10 月 6 日
- 筆記
一文攻破BCD碼轉換與各進位轉換
0.導語
最近做的項目中時刻看到時間戳用BCD[xx]來定義,那麼針對這種定義,究竟代表什麼意思,如何來使用呢,本節來闡述BCD碼與其他進位轉換以及在筆試當中,會碰到進位轉換問題,放在C/C++中,又究竟如何操作,本文來逐個攻破!
1.BCD碼
BCD碼(Binary-Coded Decimal)亦稱二進碼十進數或二-十進位程式碼。
用4位二進位數來表示1位十進位數中的0~9這10個數碼。
是一種二進位的數字編碼形式,用二進位編碼的十進位程式碼。
BCD碼這種編碼形式利用了四個位元來儲存一個十進位的數碼,使二進位和十進位之間的轉換得以快捷的進行。
這種編碼技巧最常用於會計系統的設計里,因為會計制度經常需要對很長的數字串作準確的計算。相對於一般的浮點式記數法,採用BCD碼,既可保存數值的精確度,又可免去使電腦作浮點運算時所耗費的時間。
此外,對於其他需要高精確度的計算,BCD編碼亦很常用。
BCD碼的運算規則:BCD碼是十進位數,而運算器對數據做加減運算時,都是按二進位運算規則進行處理的。這樣,當將 BCD碼傳送給運算器進行運算時,其結果需要修正。
修正的規則:當兩個BCD碼相加,如果和等於或小於 1001(即十進位數9),不需要修正;如果相加之和在 1010 到1111(即十六進位數 0AH~0FH)之間,則需加 6 進行修正;如果相加時,本位產生了進位,也需加 6 進行修正。
這樣做的原因是,機器按二進位相加,所以 4 位二進位數相加時,是按「逢十六進一」的原則進行運算的,而實質上是 2 個十進位數相加,應該按「逢十進一」的原則相加,16 與10相差 6,所以當和超過 9或有進位時,都要加 6 進行修正。
上述學習自:https://blog.csdn.net/morixinguan/article/details/50682650
BCD碼與任意進位數的轉換實現如下:
舉個例子:比如0x2A—–>二進位表示為:0010 1010 -> BCD 二進位碼 0100 0010 對應的十進位為66 十六進位42 字元為B。
/** * 任意進位轉BCD * @param src * @return */ unsigned char BcdFromHex(const BYTE &src) { unsigned char temp; temp = ((src / 10) << 4) + (src % 10); return temp; } /** * BCD轉任意進位 * @param src * @return */ unsigned char HexFromBcd(const BYTE &src) { unsigned char temp; temp = (src >> 4)*10 + (src & 0x0f); return temp; }
2.進位之間轉換
十六進位是逢16進1,八進位是逢8進1,其他進位依次類推,就不多闡述。
2.1 十進位轉任意進位
思路兩個,分為遞歸與非遞歸實現。
遞歸實現:假設十進位轉n進位,那麼就讓十進位數不斷除以n,最終餘數為0,遞歸終止,不斷彈出棧即可。
/** * 十進位轉任意進位 遞歸法 * @param vec * @param m * @param b */ void DecConvertOther(vector<char> &vec, int m, int b) { // 餘數為0 遞歸結束,開始返回棧 if(!m) return; int yushu; DecConvertOther(vec, m / b, b); yushu = m % b; if (yushu < 10) { //小於10直接輸出 vec.push_back(yushu + '0'); } else { //大於10轉換成字元輸出 vec.push_back(yushu+55+'0'); } }
非遞歸實現:每次得到的餘數插入頭部即可。
/** * 十進位轉任意進位 非遞歸法 * @param vec * @param m * @param b */ void DecConvertOther1(vector<char> &vec, int m, int b) { int yushu=0; do { yushu=m%b; vec.insert(vec.begin(),yushu+'0'); m = m/b; }while (m!=0); }
2.2 任意進位轉十進位
只需要判斷任意進位的高位是否是數字,是否在A-F或a-f之間,然後高位乘以進位再加上最低位。
/** * 任意進位轉十進位 * @param a * @param b * @return */ int OtherConvertDec(char a[], int b) { int len, i, num; int sum = 0; len = strlen(a); //求得字元串長度 for (i = 0; i < len; i++) { if (a[i] >= '0' && a[i] <= '9') num = a[i] - '0'; else if (a[i] >= 'A' && a[i] <= 'F') num = a[i] - 'A' + 10; else if (a[i] >= 'a' && a[i] <= 'f') num = a[i] - 'a' + 10; sum = sum * b + num; } return sum; }
2.3 C/C++進位轉換
在C/C++中沒有像Python中的int()
,hex()
這樣的函數,可以將十進位轉換為十六進位,但是有另外一些函數可以完成此類工作。
C實現
使用C語言來完成這個任務,將十進位數轉換為十六進位數時使用sprinf()
,而將十六進位數轉換為十進位數時使用strtol()
int de=19; char ch[10]; // 方法1 // 十進位轉十六進位 sprintf(ch,"%X",de); cout<<ch<<endl; // 十六進位轉十進位 de=strtol(ch,NULL,16); cout<<de<<endl;
C++實現
// 十進位轉十六進位 stringstream ss; ss<<hex<<de; string s = ss.str(); cout<<s<<endl; // 十六進位轉十進位 int raw; ss>>hex>>raw; cout<<raw<<endl;
3.總結
本節學習了BCD碼與其他進位的轉化以及十進位轉其他進位、其他進位轉十進位實現等,在項目開發中BCD碼使用非常廣,後面來仔細說明,歡迎訂閱公眾號光城。