为了从int中解压缩第一个和第二个4位块,我使用了以下方法:
int chunks = 0b1111_1110_1101_1100_1011_1010_1001_1000;
int mask = 0x0f << (Integer.SIZE - 4);
byte result = (byte) ((chunks & mask) >>> (Integer.SIZE - 4));
Integer.toBinaryString(result); //print "1111"
int chunks = 0b1111_1110_1101_1100_1011_1010_1001_1000;
int mask = 0x0f << (Integer.SIZE - 8);
byte result = (byte) ((chunks & mask) >>> (Integer.SIZE - 8));
Integer.toBinaryString(result); //print "1110"当整数块数位的表示从1位开始时,它会工作得很好。
当我有这样的号码从0000开始:
int chunks = 0b0000_0110_1101_1100_1011_1010_1001_1000;
int mask = 0x0f << (Integer.SIZE - 4);
byte result = (byte) ((chunks & mask) >>> (Integer.SIZE - 4));
Integer.toBinaryString(result); //print "0"
int chunks = 0b0000_0110_1101_1100_1011_1010_1001_1000;
int mask = 0x0f << (Integer.SIZE - 8);
byte result = (byte) ((chunks & mask) >>> (Integer.SIZE - 8));
Integer.toBinaryString(result); //print "110"它也很好用。
从性能的角度来看,这是一种最好的方法吗?我觉得我把事情复杂化了。
发布于 2022-06-23 11:42:49
这些操作如此琐碎,不太可能对性能产生影响。
但如果你想投入其中
byte、short、char或int时仍然使用int。因此,除非实际将值存储到byte类型的堆变量中,否则将局部变量声明为byte没有好处。关联类型强制转换意味着最低8位到32位的符号扩展操作,除非JVM的优化器设法消除它。对于第二个“4位块”,
0xf掩蔽它们。由于掩码在这两种情况下都是常量,所以对性能没有影响,至少当JIT编译器完成其工作时,字节码将更小。所以,当我们用
public static void main(String[] args) {
int[] allChunks = {
0b1111_1110_1101_1100_1011_1010_1001_1000,
0b0000_0110_1101_1100_1011_1010_1001_1000
};
for(int chunks: allChunks) {
if(firstFourBitChunkOld(chunks) != firstFourBitChunk(chunks))
throw new AssertionError();
if(secondFourBitChunkOld(chunks) != secondFourBitChunk(chunks))
throw new AssertionError();
System.out.println(Integer.toBinaryString(firstFourBitChunk(chunks)));
System.out.println(Integer.toBinaryString(secondFourBitChunk(chunks)));
System.out.println();
}
}
static int firstFourBitChunk(int chunks) {
return chunks >>> 28;
}
static int secondFourBitChunk(int chunks) {
return chunks >>> 24 & 0xf;
}
private static final int MASK_FIRST_FOUR_BITS = 0x0f << (Integer.SIZE - 4);
static byte firstFourBitChunkOld(int chunks) {
return (byte) ((chunks & MASK_FIRST_FOUR_BITS) >>> (Integer.SIZE - 4));
}
private static final int MASK_SECOND_FOUR_BITS = 0x0f << (Integer.SIZE - 8);
static byte secondFourBitChunkOld(int chunks) {
return (byte) ((chunks & MASK_SECOND_FOUR_BITS) >>> (Integer.SIZE - 8));
}例如,Integer.SIZE - 4比28更具可读性,这一点值得商榷。我必须查找Integer.SIZE是否意味着“大小(位)”或“大小(字节)”,还是完全不同的意思。名字说不出来。我认为,一般来说,在执行位操作之前,开发人员应该知道Java的int有32位。但是,由于表达式Integer.SIZE - 4是常量,所以这种选择对编译后的代码没有任何影响。
上面的代码将成功运行,我们还可以比较生成的字节码:
static int firstFourBitChunk(int);
0: iload_0
1: bipush 28
3: iushr
4: ireturn
static int secondFourBitChunk(int);
0: iload_0
1: bipush 24
3: iushr
4: bipush 15
6: iand
7: ireturn
static byte firstFourBitChunkOld(int);
0: iload_0
1: ldc #8 // int -268435456
3: iand
4: bipush 28
6: iushr
7: i2b
8: ireturn
static byte secondFourBitChunkOld(int);
0: iload_0
1: ldc #10 // int 251658240
3: iand
4: bipush 24
6: iushr
7: i2b
8: ireturni2b是附加的符号扩展操作。为了加载移位掩码,需要一个ldc指令,它从常量池加载一个值。在这种情况下,常量本身将在常量池中再占用五个字节。除此之外,代码是等价的。
如前所述,在正常、优化的执行环境中,它可能不会对实际性能产生实际影响。但是,我认为较短的变体也更易读,至少对于对位算术有必要理解的开发人员来说是如此。如果没有这种理解,就没有办法让观众读懂它。
https://stackoverflow.com/questions/72724771
复制相似问题