C#Byte []到BCD,BCD到INT

xFi*_*eTR 5 c# arrays byte bcd

我有一个由CashRegister Machine创建的Hex文件.我必须阅读此文件.

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

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

  • PLU代码格式是BCD
  • 单价1-9999999999(BCD)
  • 数量1-9999999999(BCD最后3个数字应为十进制)
  • 总金额1-9999999999(BCD)

我用二进制读取器读取hex文件,然后插入单位价格字节数组.

byte[] bytes = { data[21], data[22], data[23], data[24], data[25] }; // BCD Byte Array
Run Code Online (Sandbox Code Playgroud)

这个数组是单价.但是,如何将此数字转换为十进制数.并且信息说数量:BCD最后一个数字应该是十进制 - 这是什么意思?谢谢.

hat*_*ica 8

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;
}
Run Code Online (Sandbox Code Playgroud)

这假设每个字节都存储为大端BCD,其中最高有效位在字节的最高有效半字节中.这就是维基百科页面中描述的BCD作为更常见的实现.如果你正在处理little-endian BCD,那么for循环中的转换代码就是

    result *= 100;
    result += (10 * (bcd & 0xf));
    result += bcd >> 4;
Run Code Online (Sandbox Code Playgroud)

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

至于描述为BCD和十进制的数量,我需要查看实际值以了解他们正在谈论的内容.


Spa*_*key 5

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

0x08 0x27 0x42 0x17 0x75 = 827,421,775
Run Code Online (Sandbox Code Playgroud)

您可以像这样获得高低半字节:

int high = currentByte >> 4;
int low = currentByte & 0xF;
Run Code Online (Sandbox Code Playgroud)

将每个字节转换为数字,如下所示:

int number = 10 * high + low;
Run Code Online (Sandbox Code Playgroud)

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

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


小智 5

正确的代码:

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

您还可以通过创建公共静态类来创建 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);

    }
}
Run Code Online (Sandbox Code Playgroud)