java – 检索数字的比特
试图检索一些数字的位,例如下面字节11的标记位00001011,
(byte) 11 >> 1 << 6 >> 5 但为什么结果是10而不是2? @编辑 为了制作下面的方法,@ Yassin Hajaj的解决方案似乎更可行. public byte getBits(byte b,int from,int to) { // from & to inclusive return (byte) (b >> from << (8 - (to - from + 1))) >> (8 - to - 1); } getBits((byte) 11,1,2); // => 2 或者更加普遍的@Andreas的提示, public <T extends Number> long getBits(T n,int to) { return n.longValue() >>> from << (64 - (to - from + 1)) >>> (64 - to - 1); } getBits((byte) 11,2); // => 2 解决方法
TL; DR使用b& 6,例如(字节)(11& 6).请参阅最后的getBits()实现.
首先,将11转换为一个字节是没有意义的,因为>>运算符会将其强制转换回int值. 为了向您展示代码无效的原因,这里有一个显示所有中间步骤的程序: public static void main(String[] args) { for (byte i = 0; i <= 16; i++) { int i1 = i >> 1; int i2 = i1 << 6; int i3 = i2 >> 5; System.out.printf("%3d %s -> %3d %s -> %3d %10s -> %3d %s%n",i,bin(i),i1,bin(i1),i2,bin(i2),i3,bin(i3)); } } private static String bin(int value) { String s = Integer.toBinaryString(value); return "0000000".substring(Math.min(7,s.length() - 1)) + s; } 输出: 0 00000000 -> 0 00000000 -> 0 00000000 -> 0 00000000 1 00000001 -> 0 00000000 -> 0 00000000 -> 0 00000000 2 00000010 -> 1 00000001 -> 64 01000000 -> 2 00000010 3 00000011 -> 1 00000001 -> 64 01000000 -> 2 00000010 4 00000100 -> 2 00000010 -> 128 10000000 -> 4 00000100 5 00000101 -> 2 00000010 -> 128 10000000 -> 4 00000100 6 00000110 -> 3 00000011 -> 192 11000000 -> 6 00000110 7 00000111 -> 3 00000011 -> 192 11000000 -> 6 00000110 8 00001000 -> 4 00000100 -> 256 100000000 -> 8 00001000 9 00001001 -> 4 00000100 -> 256 100000000 -> 8 00001000 10 00001010 -> 5 00000101 -> 320 101000000 -> 10 00001010 11 00001011 -> 5 00000101 -> 320 101000000 -> 10 00001010 12 00001100 -> 6 00000110 -> 384 110000000 -> 12 00001100 13 00001101 -> 6 00000110 -> 384 110000000 -> 12 00001100 14 00001110 -> 7 00000111 -> 448 111000000 -> 14 00001110 15 00001111 -> 7 00000111 -> 448 111000000 -> 14 00001110 16 00010000 -> 8 00001000 -> 512 1000000000 -> 16 00010000 您的高位没有被清除,因为它在int值上运行.如果将所有内容更改为byte,则会得到: public static void main(String[] args) { for (byte i = 0; i <= 16; i++) { byte i1 = (byte)(i >> 1); byte i2 = (byte)(i1 << 6); byte i3 = (byte)(i2 >> 5); System.out.printf("%3d %s -> %3d %s -> %4d %s -> %3d %s%n",bin(i3)); } } private static String bin(byte value) { String s = Integer.toBinaryString(value & 0xFF); return "0000000".substring(s.length() - 1) + s; } 0 00000000 -> 0 00000000 -> 0 00000000 -> 0 00000000 1 00000001 -> 0 00000000 -> 0 00000000 -> 0 00000000 2 00000010 -> 1 00000001 -> 64 01000000 -> 2 00000010 3 00000011 -> 1 00000001 -> 64 01000000 -> 2 00000010 4 00000100 -> 2 00000010 -> -128 10000000 -> -4 22222100 5 00000101 -> 2 00000010 -> -128 10000000 -> -4 22222100 6 00000110 -> 3 00000011 -> -64 11000000 -> -2 22222110 7 00000111 -> 3 00000011 -> -64 11000000 -> -2 22222110 8 00001000 -> 4 00000100 -> 0 00000000 -> 0 00000000 9 00001001 -> 4 00000100 -> 0 00000000 -> 0 00000000 10 00001010 -> 5 00000101 -> 64 01000000 -> 2 00000010 11 00001011 -> 5 00000101 -> 64 01000000 -> 2 00000010 12 00001100 -> 6 00000110 -> -128 10000000 -> -4 22222100 13 00001101 -> 6 00000110 -> -128 10000000 -> -4 22222100 14 00001110 -> 7 00000111 -> -64 11000000 -> -2 22222110 15 00001111 -> 7 00000111 -> -64 11000000 -> -2 22222110 16 00010000 -> 8 00001000 -> 0 00000000 -> 0 00000000 这里的问题是你从>>获得的符号扩展名.甚至切换到>>>将无效,因为>>>在转变发生之前,仍然使用符号扩展强制转换为int. 要摆脱符号扩展,你必须使用b&转换为byte. 0xFF,因为&将使用符号扩展将b强制转换为int,然后按位AND运算符将删除所有这些位. 当然,如果您打算使用按位AND,只需使用它来获得所需的结果,即b& 0b00000110(或b& 6). 出于与上述相同的原因,getBits()方法不起作用. 解决方案仍然是使用按位AND运算符,但是从提供的from和to值构造位掩码. 这里的技巧是使用(1<< x)-1来创建x比特的掩码,例如1比特. 5 - > 0b00022222.因此,如果您想要2到4(包括2和4),请构建0x00022222(5!位)和0x00000011(2位),然后将它们XOR以获得0x00011100. public static byte getBits(byte b,int to) { if (from < 0 || from > to || to > 7) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return (byte)(b & mask); } 0 00000000 -> 0 00000000 1 00000001 -> 0 00000000 2 00000010 -> 2 00000010 3 00000011 -> 2 00000010 4 00000100 -> 4 00000100 5 00000101 -> 4 00000100 6 00000110 -> 6 00000110 7 00000111 -> 6 00000110 8 00001000 -> 0 00000000 9 00001001 -> 0 00000000 10 00001010 -> 2 00000010 11 00001011 -> 2 00000010 12 00001100 -> 4 00000100 13 00001101 -> 4 00000100 14 00001110 -> 6 00000110 15 00001111 -> 6 00000110 16 00010000 -> 0 00000000 对于其他原始类型,重载方法: public static byte getBits(byte value,int to) { if (from < 0 || from > to || to > 7) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return (byte)(value & mask); } public static short getBits(short value,int to) { if (from < 0 || from > to || to > 15) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return (short)(value & mask); } public static int getBits(int value,int to) { if (from < 0 || from > to || to > 31) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return value & mask; } public static long getBits(long value,int to) { if (from < 0 || from > to || to > 63) throw new IllegalArgumentException(); long mask = ((1L << (to + 1)) - 1) ^ ((1L << from) - 1); // <-- notice the change to long and 1L return value & mask; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |