为什么Java方法Integer.toBinaryString(-128)输出七位数字?

5
简单的情况是: 您有一个字节数组 byte[] message = {1,2,3}; 要以二进制形式打印出来,您可以使用以下代码:
for (byte b : message) {
    System.out.println(Integer.toBinaryString(0x100 + b).substring(1));
}

我从这个stackoverflow线程获取了这段代码。

然后得到以下输出:

00000001
00000010
00000011


但如果你在末尾标记-128...

byte[] message = { 1, 2, 3, -128 };

00000001
00000010
00000011
0000000

哇!一个七位的二进制数?我感觉这与二进制补码有关,但我越读就越困惑。我本来期望在第四行看到10000000

能有人简单地解释一下为什么-128Integer.toBinaryString是七位吗?


旧版javadoc如果该参数为负,则无符号整数值为该参数加上2^32;否则它等于该参数。将此值转换为二进制(基数为2)中的ASCII数字字符串时不需要额外前导0。但就像我说的……让我更加困惑了。



整个事情的背景是我正在尝试使用java编写一些SHA函数。别问我为什么,我自己都不知道……我只是好奇/挑战自己/折磨自己 :)

根据文档,用于SHA-256函数对消息进行填充(使其成为512位的倍数)的方法是将以下内容串联起来:

  1. 原始消息
  2. 一个单一的1
  3. 0位,直到最后64位
  4. 原始消息长度作为64位值

由于我的消息可能是ASCII 8位代码,所以我只需在#2中标记一个10000000…然后我只需要计算要添加的0字节数量,我不必为不是8的倍数的消息做规划。问题是如何制作10000000

2个回答

7
(-128 + 0x100) =
(256 - 128) = 128 = 
0b10000000

Integer.toBinaryString(0b10000000) = "10000000"

"10000000".substring(1) = "0000000"

这就是为什么我不应该在晚上编码的原因。抱歉浪费了你的时间哈哈。 - snickers10m

1

你复制的堆栈溢出线程中有一个错误。0x100在十进制中是256,所以...

0x100 + 1 = 257 = 0b100000001 (9 digits)
0x100 + (-128) = 128 = 0b10000000 (8 digits)

换句话说,由于128小于Byte.MAX_VALUE,您无法获得海报想要的填充效果。您可以选择更大的值进行填充--尝试0x200并剥离前两个字符??
值得一提的是,这些类型的错误是可以理解的,因为负字节值是Java中有点奇怪的东西。噢。

那么在我试图完成的上下文中...即使我显示的方式不同,数组中的字节是否等于10000000?我应该以其他方式插入SHA函数所需的1吗? - snickers10m
实际上我不会显示二进制...我只是这样做来检查它是否工作...我只需要一个字节数组,其中包含消息后面跟着一个10000000,这将在位运算中起作用。 - snickers10m

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接