Java storing two ints in a long
Asked Answered
D

3

38

I want to store two ints in a long (instead of having to create a new Point object every time).

Currently, I tried this. It's not working, but I don't know what is wrong with it:

// x and y are ints
long l = x;
l = (l << 32) | y;

And I'm getting the int values like so:

x = (int) l >> 32;
y = (int) l & 0xffffffff;
Dessiedessma answered 7/10, 2012 at 21:17 Comment(0)
F
75

y is getting sign-extended in the first snippet, which would overwrite x with -1 whenever y < 0.

In the second snippet, the cast to int is done before the shift, so x actually gets the value of y.

long l = (((long)x) << 32) | (y & 0xffffffffL);
int x = (int)(l >> 32);
int y = (int)l;
Fission answered 7/10, 2012 at 21:22 Comment(2)
Ah, that makes sense. One question I have is whether it matters if you bitmask using the long 0xffffffffL or the int 0xffffffff.Dessiedessma
@Dessiedessma yes it matters, if you mask with 0xffffffff (without the L) then it's just an int, so the & is a no-op and y still gets sign extended.Fission
A
14

Here is another option which uses a bytebuffer instead of bitwise operators. Speed-wise, it is slower, about 1/5 the speed, but it is much easier to see what is happening:

long l = ByteBuffer.allocate(8).putInt(x).putInt(y).getLong(0);
//
ByteBuffer buffer = ByteBuffer.allocate(8).putLong(l);
x = buffer.getInt(0);
y = buffer.getInt(4);
Angevin answered 6/8, 2014 at 22:3 Comment(2)
Java 8 has Long.BYTES, even more clear than the magic number 8.Symonds
y = buffer.getInt(4); - the argument is the byte offset, so it's 4.Extinguish
F
-1

If you want to store two Float values that are (32-bits) as a single Long value (64-bits). You can convert the bits from the float value into bits for integer value and then to the same as the previous answers.

// first method using floatToIntBits 
long method1(float x, float y) {

    int xInt = java.lang.Float.floatToIntBits(x);
    int yInt = java.lang.Float.floatToIntBits(y);
    
    return (((long)xInt) << 32) | (yInt & 0xffffffffL);
}

// second method using ByteBuffer
long method2(float x, float y) {
    return ByteBuffer.allocate(java.lang.Long.BYTES).putFloat(x).putFloat(y).getLong(0);
}
 
Frit answered 28/12, 2020 at 18:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.