Java 使用位运算符将多个值打包到一个int中
低级位操作从来不是我的强项。我将理解一些帮助理解比特操作的下列用例。考虑……/P>Java 使用位运算符将多个值打包到一个int中,java,bitwise-operators,packing,bit-packing,Java,Bitwise Operators,Packing,Bit Packing,低级位操作从来不是我的强项。我将理解一些帮助理解比特操作的下列用例。考虑……/P> int age, gender, height, packed_info; . . . // Assign values // Pack as AAAAAAA G HHHHHHH using shifts and "or" packed_info = (age << 8) | (gender << 7) | height; // Unpack with shifts and m
int age, gender, height, packed_info;
. . . // Assign values
// Pack as AAAAAAA G HHHHHHH using shifts and "or"
packed_info = (age << 8) | (gender << 7) | height;
// Unpack with shifts and masking using "and"
height = packed_info & 0x7F; // This constant is binary ...01111111
gender = (packed_info >> 7) & 1;
age = (packed_info >> 8);
int年龄、性别、身高、包装信息;
. . . // 赋值
//使用班次和“或”将包装为AAAAA G HHHHHHHHHH
打包信息=(7岁)和1岁;
年龄=(打包信息>>8);
我不确定这段代码实现了什么以及如何实现?为什么要使用神奇的数字0x7F?包装和拆包是如何完成的
这可能是位操作的一个相当长的课程,但首先让我也向您指出 解包的操作与此相反,但使用0x7F(即0b 01111111)之类的掩码来修剪字段中的其他值
gender = (packed_info >> 7) & 1;
工作起来就像
gender = 0b1011 /* shifted 7 here but still has age on the other side */
& 0b0001
/* which is */
gender = 0b1
请注意,将任何内容与1进行and运算与“保留”该位相同,与0进行and运算与“忽略”该位相同。您可以将表达式
x&mask
视为一种操作,该操作从x
中删除mask
中不存在的位(即值为0)。这意味着,packed_info&0x7F
从packed_info
中删除第七位以上的所有位
示例:如果packed_info
是二进制的1110010101010
,则packed_info&0x7f
将被删除
1110010100101010
0000000001111111
----------------
0000000000101010
因此,在height
中,我们得到packed_info
的较低7位
接下来,我们将整个packed_info
移位7,这样我们就删除了已经读出的信息。因此,我们得到(对于上一个示例中的值)111001010
性别存储在下一位,因此使用相同的技巧:&1
我们仅从信息中提取该位。其余信息包含在偏移量8处
打包也不复杂:你将年龄
,将其移位8位(因此你从11100101
得到1110010100000000
),将性别
移位7位(因此你得到00000000
),然后取高度(假设它适合较低的7位)。然后,您要将它们组合在一起:
1110010100000000
0000000000000000
0000000000101010
----------------
1110010100101010
正如评论所说,我们将把年龄、性别和身高分成15位,格式如下:
AAAAAAAGHHHHHHH
让我们从这一部分开始:
(age << 8)
其中每个A可以是0或1
左移位运算符的意思是“乘以2,多次”。在二进制中,将一个数字乘以二等于在右边加一个零
右换档操纵器与左换档操纵器相反
管道操作符是“或”,意思是将两个二进制数叠加在一起,如果其中任何一个数中都有1,则该列中的结果为1
那么,让我们提取打包信息的操作:
// Create age, shifted left 8 times:
// AAAAAAA00000000
age_shifted = age << 8;
// Create gender, shifted left 7 times:
// 0000000G0000000
gender_shifted = gender << 7;
// "Or" them all together:
// AAAAAAA00000000
// 0000000G0000000
// 00000000HHHHHHH
// ---------------
// AAAAAAAGHHHHHHH
packed_info = age_shifted | gender_shifted | height;
如果你想把一个日期存储为一个数字,也许你可以通过将年份乘以10000,将月份乘以100,再加上日期来完成。2011年7月2日等日期将编码为数字20110702:
year * 10000 + month * 100 + day -> yyyymmdd
2011 * 10000 + 7 * 100 + 2 -> 20110702
我们可以说,我们将日期编码为yyyymmdd掩码。我们可以把这次行动描述为
- 将第4年的位置向左移动
- 将第2个月的位置向左和向右移动
- 让这一天保持原样李>
- 然后将这三个值组合在一起
这与年龄、性别和身高编码发生的事情是一样的,只是作者的思维是二进制的
请参见这些值可能具有的范围:
age: 0 to 127 years
gender: M or F
height: 0 to 127 inches
如果我们将这些值转换为二进制,我们将得到:
age: 0 to 1111111b (7 binary digits, or bits)
gender: 0 or 1 (1 bit)
height: 0 to 1111111b (7 bits also)
考虑到这一点,我们可以使用掩码对年龄-性别-身高数据进行编码aaaaaaaaa ghhhhh,只是这里我们讨论的是二进制数字,而不是十进制数字
所以
- 将年龄8位向左移动
- 将性别7位左右移动
- 保持高度不变李>
- 然后将这三个值组合在一起
在二进制中,左移位运算符(是一个更简洁的答案:
aaaaaag hhhhh
包装:
Where(1 3*@offset)和((1我曾多次遇到过相同的要求。借助于按位AND运算符,这是非常容易的。只需使用两(2)的递增幂来限定您的值。要存储多个值,请将它们的相对数(2的幂)相加并得到总和。此总和将合并您选择的值。如何
只需对每个值按位执行AND,它将为未选择的值提供零(0),为已选择的值提供非零
解释如下:
1) 价值观(是、否、可能)
2) 两(2)人的权力分配
3) 我选择是,可能因此得出结论:
SUM = 1 + 4 = 5
SUM = 00000001 + 00000100 = 00000101
该值将同时存储YES和MAYBE。怎么做
1 & 5 = 1 ( non zero )
2 & 5 = 0 ( zero )
4 & 5 = 4 ( non zero )
因此,总和包括
1 = 2^0 = YES
4 = 2^2 = MAYBE.
要获得更详细的解释和实现,请访问我的,我认为在问这个问题之前,有必要阅读有关二进制数表示和位运算符的内容。评论中的图片几乎说明了一切:aaaaaaaag hhhhh感谢您提供的详细信息。它非常有用。这是一篇非常好的文章。在我读到的所有东西中,这是第一件清楚地说明发生了什么的事情。
0011 & 0101 = 0001
packed_info = AAAAAAAGHHHHHHH
0x7F = 000000001111111
(packed_info & 0x7F) = 00000000HHHHHHH = height
packed_info = AAAAAAAGHHHHHHH
(packed_info >> 7) = 0000000AAAAAAAG
1 = 000000000000001
(packed_info >> 7) & 1 = 00000000000000G
// Create age, shifted left 8 times:
// AAAAAAA00000000
age_shifted = age << 8;
// Create gender, shifted left 7 times:
// 0000000G0000000
gender_shifted = gender << 7;
// "Or" them all together:
// AAAAAAA00000000
// 0000000G0000000
// 00000000HHHHHHH
// ---------------
// AAAAAAAGHHHHHHH
packed_info = age_shifted | gender_shifted | height;
// Grab the lowest 7 bits:
// AAAAAAAGHHHHHHH &
// 000000001111111 =
// 00000000HHHHHHH
height = packed_info & 0x7F;
// right shift the 'height' bits into the bit bucket, and grab the lowest 1 bit:
// AAAAAAAGHHHHHHH
// >> 7
// 0000000AAAAAAAG &
// 000000000000001 =
// 00000000000000G
gender = (packed_info >> 7) & 1;
// right shift the 'height' and 'gender' bits into the bit bucket, and grab the result:
// AAAAAAAGHHHHHHH
// >> 8
// 00000000AAAAAAA
age = (packed_info >> 8);
year * 10000 + month * 100 + day -> yyyymmdd
2011 * 10000 + 7 * 100 + 2 -> 20110702
age: 0 to 127 years
gender: M or F
height: 0 to 127 inches
age: 0 to 1111111b (7 binary digits, or bits)
gender: 0 or 1 (1 bit)
height: 0 to 1111111b (7 bits also)
(age << 8) | (gender << 7) | height
height = value & 1111111b (preserve the 7 rightmost bits)
gender = (value >> 1) & 1 (preserve just one bit)
age = (value >> 8)
packed = age << 8 | gender << 7 | height
packed = age << 8 + gender << 7 + height
age = packed >> 8 // no mask required
gender = packed >> 7 & ((1 << 1) - 1) // applying mask (for gender it is just 1)
height = packed & ((1 << 7) - 1) // applying mask
packed = (comp1 << 0 * 10) | (comp1 << 1 * 10) | (comp1 << 2 * 10) | (comp1 << 3 * 10)
comp1 = (packed >> 0 * 10) & ((1 << 10) - 1) // 132
comp2 = (packed >> 1 * 10) & ((1 << 10) - 1) // 513
comp3 = (packed >> 2 * 10) & ((1 << 10) - 1) // 151
comp4 = (packed >> 3 * 10) & ((1 << 10) - 1) // 319
SELECT
(@offset := 10) AS `No of bits required for each component`,
(@packed := (132 << 0 * @offset) |
(513 << 1 * @offset) |
(151 << 2 * @offset) |
(319 << 3 * @offset)) AS `Packed value (132.513.151.319)`,
BIN(@packed) AS `Packed value (bin)`,
(@packed >> 0 * @offset) & ((1 << @offset) - 1) `Component 1`,
(@packed >> 1 * @offset) & ((1 << @offset) - 1) `Component 2`,
(@packed >> 2 * @offset) & ((1 << @offset) - 1) `Component 3`,
(@packed >> 3 * @offset) & ((1 << @offset) - 1) `Component 4`;
YES = 2^0 = 1 = 00000001
NO = 2^1 = 2 = 00000010
MAYBE = 2^2 = 4 = 00000100
SUM = 1 + 4 = 5
SUM = 00000001 + 00000100 = 00000101
1 & 5 = 1 ( non zero )
2 & 5 = 0 ( zero )
4 & 5 = 4 ( non zero )
1 = 2^0 = YES
4 = 2^2 = MAYBE.