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