【问题标题】:C# Byte[] to BCD and BCD to INTC# Byte[] 转 BCD 和 BCD 转 INT
【发布时间】:2012-07-26 21:55:27
【问题描述】:

我有一个由 CashRegister Machine 创建的 Hex 文件。我必须把这个文件读进去。

文件使用下面详述的格式。它就像套接字数据包。

代码数据:2 字节
PLU 代码数据:7 字节
单价数据:5 字节
数量数据:5 字节
总量数据:5 字节
PLU 名称数据:18 字节
税率数据:1 个字节
长度:24 + 19 字节

  • PLU 码格式为 BCD
  • 单价1-9999999999(BCD)
  • 数量 1-9999999999(BCD 后三位数字应为十进制)
  • 总金额1-9999999999(BCD)

我用二进制阅读器读入了 hex 文件,然后插入到 Unit Price 字节数组中。

byte[] bytes = { data[21], data[22], data[23], data[24], data[25] }; // BCD Byte Array

这个数组是单价。但是我怎样才能将这个数字转换为十进制。并且信息说对于数量:BCD最后一个数字应该是十进制 - 这是什么意思?谢谢。

【问题讨论】:

  • 非常不清楚的问题,请澄清/详细说明。
  • 显示byte[] bytes 内容的示例以及您期望的输出。看看BinaryReader.ReadDecimal()
  • 我试图详细说明它。 bytes 有一个数字,但我如何读取为 int。
  • 能否在以“Code Data : 2 Byte”开头的行中加一些逗号,以便清楚地分隔各项?

标签: c# arrays byte bcd


【解决方案1】:

BCD 数字将 0-9 的值编码为 4 位。在打包的 BCD(可能是您正在处理的内容)中,一个字节用于包含两个值 0-9,一个在字节的每个半字节(4 位)中。要转换为 int,您必须进行一些操作。例如,以下代码会将 BCD 字节数组转换为 int,最多可容纳 9 位数字。如果输入的位数超过 9 bcd,请使用 long。

// assume byte[] bcds is input
int result = 0;
foreach(byte bcd in bcds) {
    result *= 100;
    result += (10 * (bcd >> 4));
    result += bcd & 0xf;
}

这假设每个字节都存储为大端 BCD,其中最高有效位在字节的最高有效半字节中。这是Wikipedia page for BCD 中描述的更常见的实现。如果您正在处理 little-endian BCD,则 for 循环中的转换代码将是

    result *= 100;
    result += (10 * (bcd & 0xf));
    result += bcd >> 4;

您还需要确保您的数组具有正确的字节顺序,即数组中的第一个字节是否包含最高有效两位数或最低有效两位数。例如,数字 123456 使用打包的 BCD 将适合 3 个字节。 12 是 byte[0] 还是 byte[2]?如果您的字节序与我的假设不同,则需要调整上面的循环以反转顺序。我假设 12 在 byte[0] 中(大端,最左边的字节中的最高有效数字)。

至于描述为 BCD 和小数的数量,我需要查看实际值才能理解它们在说什么。

【讨论】:

  • bcd >>= 4;不起作用。您需要复制字节才能对其进行修改。
  • @SamLeach - 感谢您的提醒。我把它写在了我的头上。我已经按照您的建议修复了它,还修复了我在执行此操作时注意到的另一个错误。上面的代码已经过测试,现在可以运行了。
【解决方案2】:

每个字节是两个十进制数字,每个半字节一个。如果将字节显示为十六进制,则可以轻松读取数字。

0x08 0x27 0x42 0x17 0x75 = 827,421,775

你可以像这样得到高位和低位:

int high = currentByte >> 4;
int low = currentByte & 0xF;

像这样将每个字节转换为数字:

int number = 10 * high + low;

但请记住,每个字节比下一个字节大 100 倍。

数量有 3 位小数,只需将最终数字除以 1,000 即可得到实际值。

【讨论】:

    【解决方案3】:

    正确的代码:

    // assume byte[] bcds is input
    int result = 0;
    foreach(byte bcd in bcds) {
        result *= 100;
        result += (10 * (bcd >> 4));
        result += bcd & 0xf;
    }
    

    您还可以通过创建公共静态类来为 byte[] 创建自定义扩展:

    public static class BitConverterExtension
    {
        public static UInt64 FromBCDToExtUInt64(this byte[] b, byte[] bcds, uint nBytes, uint startOf)
        {
            UInt64 result = 0;
            uint i = 0;
    
            for (i = 0; i < nBytes; i++)
            {
                result *= 100;
                result += (UInt64)(10 * (bcds[startOf + i] >> 4));
                result += (UInt64)(bcds[startOf + i] & 0xf);
            }
    
            return (result);
    
        }
    }
    

    【讨论】:

      【解决方案4】:

      我编写了这段代码并为我工作:

       public uint BCD5ToInt(byte [] bcd)
      {
      uint outInt=0;
      
         for (int i = 0; i < bcd.Length; i++)
         {
             int mul = (int)Math.Pow(10,(i*2));
             outInt += (uint) (((bcd[i] & 0xF)) * mul);
             mul = (int)Math.Pow(10, (i * 2) + 1);
             outInt +=(uint)( ((bcd[i] >> 4) ) * mul);
         }
      
         return outInt;
      }
      

      这是反码:

        // Convert an unsigned integer into 5 bytes of 
          public byte[] IntToBCD5(uint numericvalue, int bytesize = 5)
          {
              byte[] bcd = new byte[bytesize];
              for (int byteNo = 0; byteNo < bytesize; ++byteNo)
                  bcd[byteNo] = 0;
              for (int digit = 0; digit < bytesize * 2; ++digit)
              {
                  uint hexpart = numericvalue % 10;
                  bcd[digit / 2] |= (byte)(hexpart << ((digit % 2) * 4));
                  numericvalue /= 10;
              }
              return bcd;
          }
      

      这是测试代码:

       public void test()
          {
              uint firstInt = 987654321;
              var array = IntToBCD5(firstInt);
              var outInt = BCD5ToInt(array);
              MessageBox.Show(outInt.ToString());
          }
      

      【讨论】:

        【解决方案5】:

        我的回答可能有点晚了,但这是我解决问题的方法:

        1- 首先我需要找到数字的长度,例如:3422 -> 4, 100 -> 3

        public static class NumbersUtility
        {
            public static int FindNumberLength(int number)
            {
                return Convert.ToInt32( Math.Floor(Math.Log(number,10))+1);
            }
        
            public static int FindNumberDivisor(int number)
            {
                return Convert.ToInt32(Math.Pow(10, FindNumberLength(number)-1));
            }
        
            public static int[] FindNumberElements(int number)
            {
                int[] elements = new int[FindNumberLength(number)];
                int divisor = FindNumberDivisor(number);
                for (int i = 0; i < elements.Length; i++)
                {
                    elements[i] = number/divisor;
                    number %= divisor;
                    divisor /= 10;
                }
                return elements;
            }
        }
        

        之后,我将数字拆分为一个数组,这样可以更轻松地遍历和处理数字。但是有一个警告,如果数字是奇数长度,则必须在数组的开头添加一个零。

               public static byte[] IntToBCD(int[] input, bool isLittleEndian = false)
            {
                byte[] outArr = new byte[Convert.ToInt32(Math.Ceiling((double) input.Length/2))];
        
                //Handle the case of an odd number in which a zero should be added at the beginning
                if (input.Length%2 != 0)
                {
                    //Use a temp array to expand the old one, you can use lists or 
                    //anyother datastructure if you wish to
                    int[] newInput = new int[input.Length+1];
                    Array.Copy(input,0,newInput,1,input.Length);
                    newInput[0] = 0;
                    input = newInput;
                    //Dispose the temp array
                    newInput = null;
                }
        
                for (int i = 0; i < outArr.Length; i++)
                {
        
                    outArr[i]=(byte)(input[i*2]<<4);
                    outArr[i]|=(byte)(input[i*2+1]);
                }
                return outArr;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-25
          • 1970-01-01
          • 2021-12-03
          • 1970-01-01
          相关资源
          最近更新 更多