一文攻破BCD码转换与各进制转换
0.导语
最近做的项目中时刻看到时间戳用BCD[xx]来定义,那么针对这种定义,究竟代表什么意思,如何来使用呢,本节来阐述BCD码与其他进制转换以及在笔试当中,会碰到进制转换问题,放在C/C++中,又究竟如何操作,本文来逐个攻破!
1.BCD码
用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码使用非常广,后面来仔细说明,欢迎订阅公众号光城。