为什么在 Java 中将字节数组转换为 BitSet 得到错误的位表示
Why is wrong bit representation got by converting byte array to BitSet in Java
我试图转换一个字节数组以便使用它的位表示。
输入:
byte[] values = new byte[]{21, 117, 41, -1};
我想从字节数组创建一个 BitSet 对象,但我将其拆分以调查问题并尝试从数组的每个元素创建多个 BitSet 对象。
BitSet 对象的创建方式如下:
BitSet bitSetTwentyOne = BitSet.valueOf(new byte[]{21});
BitSet bitSetOneHundredSevenTeen = BitSet.valueOf(new byte[{117});
BitSet bitSetFourtyOne = BitSet.valueOf(new byte[]{41});
BitSet bitSetMinusOne = BitSet.valueOf(new byte[]{-1});
使用以下方法打印出位:
private String getBits(BitSet bitSet) {
StringBuilder bitsBuilder = new StringBuilder();
for (int i = 0; i < bitSet.length(); i++) {
bitsBuilder.append(bitSet.get(i) == true ? 1 : 0);
}
return bitsBuilder.toString();
}
输出:
bitSetTwentyOne: 10101 but expected -> 00010101 (BitSet::length = 5)
bitSetOneHundredSevenTeen: 1010111 but expected -> 01110101 (BitSet::length = 7)
bitSetFourtyOne: 100101 but expected -> 00101001 (BitSet::length = 6)
bitSetMinusOne: 11111111 but it is as expected at least (BitSet::length = 8)
即使需要用零填充,我也希望所有值都是 8 位宽度。我不明白为什么在转换 117 和 41.
时会给出错误的二进制值
您似乎在向后打印这些位。请注意您的输出(所需的前导零除外)如何是您预期输入的镜像。
使用您的代码,传入 4
,应该是 100
,我得到 001
。 0
位似乎是最低有效位,而不是最高有效位。要更正此问题,请向后循环索引。 -1
和 41
除了前导零之外正确的原因是它们的位集表示是回文。
要在前面添加前导零,请从 8
中减去 length()
并打印那么多的零。 length()
方法仅 returns 表示数字所需的位数。您需要自己编写代码;没有 BitSet
前导零功能。
length()
使用最高位 1 传递 逻辑 长度。
size()
会给出 8。
cardinality()
会给出 bit 1 的个数。
所以你应该使用 size()
.
然后是little endian格式的bits,你先输出bit 0再反转
private String getBits(BitSet bitSet) {
StringBuilder bitsBuilder = new StringBuilder();
for (int i = 0; i < bitSet.size(); ++i) {
bitsBuilder.insert(0, bitSet.get(i) ? '1' : '0');
}
return bitsBuilder.toString();
}
我试图转换一个字节数组以便使用它的位表示。
输入:
byte[] values = new byte[]{21, 117, 41, -1};
我想从字节数组创建一个 BitSet 对象,但我将其拆分以调查问题并尝试从数组的每个元素创建多个 BitSet 对象。
BitSet 对象的创建方式如下:
BitSet bitSetTwentyOne = BitSet.valueOf(new byte[]{21});
BitSet bitSetOneHundredSevenTeen = BitSet.valueOf(new byte[{117});
BitSet bitSetFourtyOne = BitSet.valueOf(new byte[]{41});
BitSet bitSetMinusOne = BitSet.valueOf(new byte[]{-1});
使用以下方法打印出位:
private String getBits(BitSet bitSet) {
StringBuilder bitsBuilder = new StringBuilder();
for (int i = 0; i < bitSet.length(); i++) {
bitsBuilder.append(bitSet.get(i) == true ? 1 : 0);
}
return bitsBuilder.toString();
}
输出:
bitSetTwentyOne: 10101 but expected -> 00010101 (BitSet::length = 5)
bitSetOneHundredSevenTeen: 1010111 but expected -> 01110101 (BitSet::length = 7)
bitSetFourtyOne: 100101 but expected -> 00101001 (BitSet::length = 6)
bitSetMinusOne: 11111111 but it is as expected at least (BitSet::length = 8)
即使需要用零填充,我也希望所有值都是 8 位宽度。我不明白为什么在转换 117 和 41.
时会给出错误的二进制值您似乎在向后打印这些位。请注意您的输出(所需的前导零除外)如何是您预期输入的镜像。
使用您的代码,传入 4
,应该是 100
,我得到 001
。 0
位似乎是最低有效位,而不是最高有效位。要更正此问题,请向后循环索引。 -1
和 41
除了前导零之外正确的原因是它们的位集表示是回文。
要在前面添加前导零,请从 8
中减去 length()
并打印那么多的零。 length()
方法仅 returns 表示数字所需的位数。您需要自己编写代码;没有 BitSet
前导零功能。
length()
使用最高位 1 传递 逻辑 长度。size()
会给出 8。cardinality()
会给出 bit 1 的个数。
所以你应该使用 size()
.
然后是little endian格式的bits,你先输出bit 0再反转
private String getBits(BitSet bitSet) {
StringBuilder bitsBuilder = new StringBuilder();
for (int i = 0; i < bitSet.size(); ++i) {
bitsBuilder.insert(0, bitSet.get(i) ? '1' : '0');
}
return bitsBuilder.toString();
}