一文攻破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码使用非常广,后面来仔细说明,欢迎订阅公众号光城。