简单的场景: 你有一个字节数组
byte[] message = { 1, 2, 3 };
要以二进制打印出来,您可以使用以下代码:
for (byte b : message) {
System.out.println(Integer.toBinaryString(0x100 + b).substring(1));
}
(从this stack overflow thread获得该代码)
获得此输出:
00000001
00000010
00000011
但如果你在最后标记-128 ......
byte[] message = { 1, 2, 3, -128 };
00000001
00000010
00000011
0000000
哇!七位二进制数?我觉得这与两个补充有关,但我试着读的越多,我就越困惑。我期待10000000
出现在第四行而不是......
任何人都可以用相对简单的术语解释为什么Integer.toBinaryString
的{{1}}是七位数?
Ye olde javadoc说-128
但就像我说的那样......只是让我困惑。
这一切的背景是我尝试编写java中的一些SHA函数。不要问我为什么,我甚至都不知道......我只是好奇/挑战自我/挫败自己:)
根据the documentation在SHA-256函数中使用的消息的填充(使其为位长的512的倍数)是以下的串联:
The unsigned integer value is the argument plus 2^32 if the argument is negative; otherwise it is equal to the argument. This value is converted to a string of ASCII digits in binary (base 2) with no extra leading 0s.
位1
位到最后64位由于我的消息很可能是ASCII 8位代码,我只需要为{2}标记0
...然后我可以将10000000
BYTES的数量计算为加上,我不应该计划不是8的倍数的消息。问题在于0
。
答案 0 :(得分:7)
(-128 + 0x100) =
(256 - 128) = 128 =
0b10000000
Integer.toBinaryString(0b10000000) = "10000000"
"10000000".substring(1) = "0000000"
答案 1 :(得分:1)
您复制的堆栈溢出线程中存在错误。 0x100
十进制为256,所以......
0x100 + 1 = 257 = 0b100000001 (9 digits)
0x100 + (-128) = 128 = 0b10000000 (8 digits)
换句话说,由于128小于Byte.MAX_VALUE,因此您无法获得海报所预期的填充效果。你可以选择一个更大的值来填充 - 尝试0x200并删除前两个字符??
FWIW,可以理解这些类型的错误b / c负字节值有点奇怪的java事情。哦,好吧。