【问题标题】:How to convert two's complement binary byte[] to decimal?如何将二进制补码字节 [] 转换为十进制?
【发布时间】:2014-08-20 09:32:33
【问题描述】:

我在字节选项卡 (byte[]) 中接收来自 RS422 通信的数据。

我的一些数据是二进制补码,规则如下:

Significant bits   Two's complement
MSB  LSB
00000000           0
00000001           + LSB
01111111           + MSB - LSB
10000000           - MSB
10000001           - MSB + LSB
11111111           - LSB     

要将 byte[] 数据转换为十进制,纯二进制,我使用以下代码:

Byte b05 = new Byte(new Integer(0x7A).byteValue()); // I use those bytes for my test
Byte b06 = new Byte(new Integer(0x00).byteValue());

Byte[] byteTabDay = new Byte[2] ;
byteTabDay[0] = b05 ;
byteTabDay[1] = b06 ;    

int valueDay  =  byteTabDay[1] << 8 | byteTabDay[0] ; 
System.out.println("day :" + valueDay); // print 122

但我不知道如何像以前一样转换包含二进制补码数据的 byte[]:

Byte b20 = new Byte(new Integer(0x00).byteValue());
Byte b21 = new Byte(new Integer(0xFF).byteValue());
Byte b22 = new Byte(new Integer(0x3C).byteValue());

理论上,这些数据包含的值(或多或少):1176

所以我需要帮助,因为我不明白如何将包含二进制补码的字节数据转换为十进制。

【问题讨论】:

  • 你为什么到处使用盒装类型?不要做Byte b21 = new Byte(new Integer(0xFF).byteValue());,做byte b21 = (byte) 0xFF;
  • 我不知道你的“规则”想说什么。您的第一个代码 sn-p 建议了一个微不足道的多字节 int 值,但不清楚为什么您在用两个字节到三个字节做同样的事情时会遇到麻烦。您如何得出1176.61254 的值?浮点数,真的吗?
  • 第一个sn-p只能是正值,第二个sn-p可以是负值也可以是正值。没错,我不能有浮点数,所以我的例子是 1176

标签: java byte twos-complement


【解决方案1】:

二进制补码是表示包含负数的数字的标准。

对于三位数字:

      Base 2     (One's       Two's
                 complement)  complement
000 =  0
001 =  1
010 =  2
011 =  3
100 =  4             -3         -4
101 =  5             -2         -3
110 =  6             -1         -2
111 =  7             -0         -1

Java 假定二进制补码:最高有效位为 1 表示负数。 在 java byte、short、int、long 中也是有符号的。 顺便说一句,您对原始类型使用了 Object 包装器。原始类型更直接。

byte b05 = (byte) 0x7A;
byte b06 = (byte) 0x00; // MSB, positive as < 0x80

nyte[] byteTabDay = new byte[2];
byteTabDay[0] = b05;
byteTabDay[1] = b06;    

int valueDay  =  ((int) byteTabDay[1]) << 8) | (0xFF & byteTabDay[0]); 
System.out.println("day :" + valueDay); // print 122

必须做的:保留最高有效字节的符号扩展,但对于其他字节,通过用 0xFF 屏蔽它们,将它们保持为 8 位。

【讨论】:

  • 对。 b22 如果它是负数:作为 int 将其符号位 (8) 扩展到左侧,保持相同的负值。
  • 所以如果我想转换一个数字,它是 3 字节: byte b20 = (byte)0x00 ;字节 b21 = (字节)0xFF ;字节 b22 = (字节)0x3C ;我必须写: int newLatValue = (((int) b22)
【解决方案2】:

将包含二进制补码值的任意字节数组转换为十进制表示的最简单方法是new BigInteger(bytearray).toString()

然而,这要求数据采用大端字节序。如果数据在您的问题中显示为小端顺序,则必须将其反转以与BigInteger 一起使用。

byte[] bytearray={ 0x7A, 0x00 };
ByteBuffer b=ByteBuffer.allocate(bytearray.length);
for(int ix=bytearray.length; ix>0; ) b.put(bytearray[--ix]);
System.out.println(new BigInteger(b.array()).toString()); // print 122

如果数组的长度匹配一个标准的原始值类型大小,可以使用ByteBuffer直接获取值:

byte[] bytearray={ 0x7A, 0x00 };
System.out.println(ByteBuffer.wrap(bytearray)
    .order(ByteOrder.LITTLE_ENDIAN).getShort()); // print 122

但是,不要期望值 1176.61254 作为结果。这不可能。 如果您认为这是编码值,则必须调整您的规范。浮点值没有标准的三字节格式。

【讨论】:

  • 你的价值是对的,我或多或少有 1176。谢谢
猜你喜欢
  • 2013-09-28
  • 1970-01-01
  • 2014-11-15
  • 2014-03-01
  • 2016-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多