I have two integers that I need to pass through one integer and then get the values of two integers back.
I am thinking of using Logic Operators (AND, OR, XOR, etc) .
Using the C programming language, it could be done as follows assuming that the two integers are less than 65535.
void take2IntegersAsOne(int x)
{
// int1 is stored in the bottom half of x, so take just that part.
int int1 = x & 0xFFFF;
// int2 is stored in the top half of x, so slide that part of the number
// into the bottom half, and take just that part.
int int2 = (x >> 16) & 0xFFFF
// use int1 and int2 here. They must both be less than 0xFFFF or 65535 in decimal
}
void pass2()
{
int int1 = 345;
int int2 = 2342;
take2Integers( int1 | (int2 << 16) );
}
This relies on the fact that in C an integer is stored in 4 bytes. So, the example uses the first two bytes to store one of the integers, and the next two bytes for the second. This does impose the limit though that each of the integers must have a small enough value so that they will each fit into just 2 bytes.
The shift operators << and >> are used to slide the bits of an integer up and down. Shifting by 16, moves the bits by two bytes (as there are 8 bits per byte).
Using 0xFFFF represents the bit pattern where all of the bits in the lower two bytes of the number are 1s So, ANDing (with with & operator) causes all the bits that are not in these bottom two bytes to be switched off (back to zero). This can be used to remove any parts of the 'other integer' from the one you're currently extracting.
There are two parts to this question. First, how do you bitmask two 32-bit Integers into a 64-bit Long Integer?
As others have stated, let's say I have a function that takes an X and Y coordinate, and returns a longint representing that Point's linear value. I tend to call this linearization of 2d data:
public long asLong(int x, int y) {
return ( ((long)x) << 32 ) | y;
}
public int getX(long location) {
return (int)((location >> 32) & 0xFFFFFFFF);
}
public int getY(long location) {
return (int)(location & 0xFFFFFFFF);
}
Forgive me if I'm paranoid about order of operations, sometimes other operations are greedier than <<, causing things to shift further than they should.
Why does this work? When might it fail? It's convenient that integers tend to be exactly half the size of longints. What we're doing is casting x to a long, shifting it left until it sits entirely to the left of y, and then doing a union operation (OR) to combine the bits of both.
Let's pretend they're 4-bit numbers being combined into an 8-bit number:
x = 14 : 1110
y = 5 : 0101
x = x << 4 : 1110 0000
p = x | y : 1110 0000
OR 0101
---------
1110 0101
Meanwhile, the reverse:
p = 229 : 1110 0101
x = p >> 4 : 1111 1110 //depending on your language and data type, sign extension
//can cause the bits to smear on the left side as they're
//shifted, as shown here. Doesn't happen in unsigned types
x = x & 0xF:
1111 1110
AND 0000 1111
-------------
0000 1110 //AND selects only the bits we have in common
y = p & 0xF:
1110 0101
AND 0000 1111
-------------
0000 0101 //AND strikes again
This sort of approach came into being a long time ago, in environments that needed to squeeze every bit out of their storage or transmission space. If you're not on an embedded system or immediately packing this data for transmission over a network, the practicality of this whole procedure starts to break down really rapidly:
If it's so bad, what are the alternatives?
This is why people were asking you about your language. Ideally, if you're in something like C or C++, it'd be best to say
struct Point { int x; int y; };
public Point getPosition() {
struct Point result = { 14,5 };
return result;
}
Otherwise, in HLLs like Java, you might wind up with an inner class to achieve the same functionality:
public class Example {
public class Point {
public int x;
public int y;
public Point(int x, int y) { this.x=x; this.y=y; }
}
public Point getPosition() {
return new Point(14,5);
}
}
In this case, getPosition returns an Example.Point - if you keep using Point often, promote it to a full class of its own. In fact, java.awt has several Point classes already, including Point and Point.Float
Finally, many modern languages now have syntactic sugar for either boxing multiple values into tuples or directly returning multiple values from a function. This is kind of a last resort. In my experience, any time you pretend that data isn't what it is, you wind up with problems down the line. But if your method absolutely must return two numbers that really aren't part of the same data at all, tuples or arrays are the way to go.
The reference for the c++ stdlib tuple can be found at http://www.cplusplus.com/reference/std/tuple/
Well.. @Felice is right, but if they both fit in 16 bit there's a way:
output_int = (first_int << 16) | second_int
^
means 'or'
to pack them, and
first_int = output_int & 0xffff
second_int = (output int >> 16) & 0xffff
^
means 'and'
to extract them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With