Packing values ​​in one int

Say I have a couple of variables like apple, orange, banana

I have 8 apples, 1 orange, 4 bananas.

Is it possible to somehow convert these values ​​into a single whole, and also return to the original values ​​based on the calculated integer value?

I found an example on the Internet.

int age, gender, height; short packed_info; . . . // packing packed_info = (((age << 1) | gender) << 7) | height; . . . // unpacking height = packed_info & 0x7f; gender = (packed_info >>> 7) & 1; age = (packed_info >>> 8); 

But it does not work as it should when I entered random numbers.

+4
source share
5 answers

How to do it

Yes you can do it. A simple way to do this is what you are doing now, this is the distribution of different bits of an integer to different values. For you, this looks like a 32-bit int:

 |3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 | | | |1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 | 7 |6 5 4 3 2 1 0| | Age |Gender| Height | 

When you change bit eight to the right, you take only the age parts of the number. If you moved seven to the right and masked it 1, i.e. value >>> 7 & 1 , you will get an answer. And if you just mask the bottom seven bits (i.e. value & 0x7F ), then you get the height.

Why is it fragile

Your example is missing something important: a range of values. For example, the height value can never exceed 127. If you try to save a height of 128 or higher, the way you write it now will cause part of the height to overwrite the floor, because you need eight bits to store a large value. This is why random numbers do not work.

In the same way, if someone accidentally puts a gender that is not zero or one, then he will ruin part of the age value, because you simply cannot keep a number that is high in one bit.

A way to fix this in the assignment is to insert bit masks, for example:

 packed_info = (((age << 1) | (gender & 1)) << 7) | (height & 0x7f); 

When you do this, you can be sure that gender will not overwrite age and height will not overwrite others. However, if you set it to a height greater than 127, mod 127 will be used.

Why you should not usually

Because it is prone to errors and integers do not take up a lot of memory. You can't just remember its int anymore, you need to remember what the bit layout looks like. It’s easier to just save three int s.

However, this kind of thing is still being done when the transmission speed matters. (For example, digital television or other video, digital audio, Ethernet protocols, etc.)

+11
source

First: your idea is in order, you are changing it incorrectly (or it threatens you).

This suggests that this is more of a mathematical question than a Java question, but let the game continue :).

In fact, you can pack any number of integers into a single integer, assuming the number can grow unlimitedly, with something like:

(Let n be the resulting number, n1 ... nk numbers and Pn the nth prime number)

 n = 2^n1 + 3^n2 + 5^n3 ... Pn^nk 

Now this will not happen, since unpacking is slow, and you cannot pack large numbers or a large number of them.

No matter what the technique, you will always have this problem: the larger your numbers, the more they will be, the more difficult it will be to pack them.

Where am I going with this? You can use bitwise packaging or any other kind that you like if you actually have space in integers to store your information. The bitwise logic you used will be very good!

+1
source

You can pack and unpack signed values. For example, to pack two ints into one:

 int pack2(int val1, int val2) { int ret_val = (((val1 & 0xFFFF) << 16) | (val2 & 0xFFFF)); return ret_val; } int[] unpack2(int packed) { int val1 = ((packed >> 16) & 0xFFFF); // restore sign if ((val1 & 0x8000) != 0) val1 |= 0xFFFF0000; int val2 = (packed & 0xFFFF); // restore sign if ((val2 & 0x8000) != 0) val2 |= 0xFFFF0000; return new int[] { val1, val2 }; } 

Of course, you must make sure that both values ​​are between -0x7FFF and 0x7FFF (in the case of two values).

+1
source

You can do this, although it depends on the size of the target integer and the possible range of “fruit” variables. If the range is larger, you need a different bitfield configuration. The number of bits required for a particular field is log_2 (maximum range value).

0
source

Such packaging is conditional.

In your example

  • height is 7 bits (0 to 127)
  • gender is 1 bit (0 or 1)
  • age takes the remaining available bits (23 bits if signed, 24 if not, for int in Java)

    <-Age → → -floor → <-height →

If you use random numbers, you are likely to overflow with a limited record size (defined by a legend). For example, if you set 128 for height, you force the LSb field (right bit) to be 1 .

0
source

Source: https://habr.com/ru/post/1333623/


All Articles