简单接触BCD码,以及使用C#简单实现BCD转换
BCD码(Binary-Coded Decimal),使用4位二进制数来表示1位十进制中的0~9这10个数码,
BCD码常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。
BCD码有很多形式,本次只讨论8421码,
如果一个字节的二进制是 0101 0101,则十进制为85,那么BCD就是55(BCD用4个bit表示一个0-9的数值,0101是5,8个bit就是2位,即5*10+5=55),
如果用一串字节数组来描述BCD码,那么字节数组中每个字节前4位和后4位的范围为000-1001,这和十六进制很像,十六进制的低4位表示0-F,范围0000-1111,
个人感觉BCD码(8421码)和没有ABCDEF的十六进制完全一样,如果确认BCD码为8421码,是不是就能将字节数组转成十六进制字符串来表示BCD码呢?
不过8421码本身就很简单,也可以自己实现一个,
public static void Start() { var rd = new Random(); for (int i = 0; i < 20; i++) { var num = rd.NextInt64(10000000000000, 99999999999999); string bcdString = num.ToString(); //模拟BCD码 var bcdCode = new BCDCode(bcdString); var bytes = bcdCode.ToBytes(); //其字节数组 var other = new BCDCode(bytes, 0, bytes.Length); //测试通过字节数组转BCD吗 var hex = BitConverter.ToString(bytes).Replace("-", ""); Console.WriteLine($"{i},{bcdString},{bcdString == other.Value},{other.Value},{hex},{hex == bcdString}"); } }
/// <summary> /// 一个用于描述BCD码的结构体 /// </summary> public readonly struct BCDCode { public readonly string Value { get; } static string Validate(string value) { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value), "BCD 值不能为空"); if (value.Length % 2 != 0) throw new ArgumentException("BCD 值必须是偶数长度", nameof(value)); if (!value.All(c => char.IsDigit(c))) throw new ArgumentException("BCD 值只能包含数字字符", nameof(value)); return value; } /// <summary> /// 从字符串创建 BCD 码 /// </summary> public BCDCode(string value) => Value = Validate(value); /// <summary> /// 从字节数组创建 BCD 码 /// </summary> public BCDCode(byte[] bytes, int startIndex, int length) { char[] result = new char[length * 2]; int idx = 0; for (int i = 0; i < length; i++) { var b = bytes[startIndex + i]; //每个字节分两份,分别将前4位和后4位转成数字字符 result[idx++] = (char)((b >> 4) + '0'); //加上字符0正好能对应上ASCII的数字 result[idx++] = (char)((b & 0x0F) + '0'); } Value = new string(result); Validate(Value); } /// <summary> /// 转换为字节数组 /// </summary> public byte[] ToBytes() { byte[] bytes = new byte[Value.Length / 2]; for (int i = 0; i < bytes.Length; i++) { var b1 = (byte)(Value[i * 2] - '0'); //减去字符0将ASCII字符还原为4bit表示的数值 var b2 = (byte)(Value[i * 2 + 1] - '0'); bytes[i] = (byte)((b1 << 4) | b2); //将2个数值合并为一个字节 } return bytes; } }

浙公网安备 33010602011771号