I need to extract certain bit ranges from with a long value, for example:
long input = 15367 (11110000000111)
What I need to then do is to extract two long values from the original long,
First long is 5 bits starting from bit 0, so bits 0:4 = 7 (0111)
Second long is 56 bits starting from bit 8, so bits 7:55 = 60 (1111000)
I know this can be done with bit shifting and masking, however I'm not entirely sure how to implement that so it's dynamic each time, as each time I need to do this, the long will be different, and so too will the specific bit ranges.
I've been reading about BitSets and BitArrays, however I'm not entirely sure these are the right things for the job.
Any advice on the best way to implement this would be greatly appreciated.
Thanks!
To extract nrBits bits starting from offset offset, you can do:
public static long extractSub(final long l, final int nrBits, final int offset)
{
final long rightShifted = l >>> offset;
final long mask = (1L << nrBits) - 1L;
return rightShifted & mask;
}
Note the user of the >>> right shift operator; this is so you don't carry the sign bit around.
As to (1L << nrBits) - 1L, that is 2^nrBits - 1. The L is to have long constants.
Also note that there is no "bounds checking" (for instance, an offset or number of bits greater than 63 or negative).
To extract bits between bit x and bit y, where x is the larger of the two numbers, you could say
long mask = (Math.pow(2,x+1)-1)- (Math.pow(2,y+1)-1);
long extract = input & mask;
Related
I have an external system outputting 2 unsigned integers that represent a 64 bit unsigned int. Java picks these up and converts them to signed integers. I have called them lower and upper in java. I would like to put this back into a 64 bit int. I understand I have to use signed int which is ok.
I started off casting them both to long, shift the upper long by 32 bits and then trying to add them but it didn't go so well because the cast moves the sign bit of the integers. So I started to muck around with adding 2^31 and other messy stuff. How can I do this cleanly?
Here is an example, using 2 x 8 bit numbers to 16 bits for simplicity
Higher = 00000000 lower = 11111111
Desired result
0000000011111111
Result I get
1000000001111111
EDIT: This is code that I believe works ok (I haven't fully tested) but I was hoping for something cleaner.
private static long combineCounters(int lower, int upper) {
long lower2 = (long)lower;
if(lower2 < 0) lower2 += (2L<<31);
long upper2 = (long)upper;
if(upper2 < 0) upper2 += (2L<<31);
long result = lower2 | (upper2<<32);
return result;
}
For your case, first of all, you should store your integer values correctly into a long. To do so, you can AND your value with 0xFFFFFFFFL (a long with first 32 bit as 1).
Here is an example which works:
int upperInt = ...
int lowerInt = ...
long hi = upperInt & 0xFFFFFFFFL;
long lo = lowerInt & 0xFFFFFFFFL;
long c = (hi << 32) | lo;
System.out.println(String.format("0x%X", c));
int higher = ...
int lower = ...
long result = (((long) higher) << 32) | ((long) lower) & 0xFFFFFFFFL;
How can I zero out the last 32 bits of a double, in java, as efficiently as possible?
Try this.
private static final long ZERO_OUT_LAST_32_BITS = 0xffffffff00000000L;
public static void main(String[] args) {
double number = 2.5;
long numberBits = Double.doubleToLongBits(number);
double result = Double.longBitsToDouble(numberBits & ZERO_OUT_LAST_32_BITS);
}
It zeroes out the last 32 bits of the binary representation of your double by using a binary AND operation.
However, make sure you know exactly what and why you are doing - I would at least expect an explaining comment next to code like this.
Convert to long and mask away the desired bits, convert back:
long l = Double.doubleToLongBits();
l &= 0xFFFFFFFF00000000L;
double truncated = Double.longBitsToDouble(l);
Although I'm not sure what you're trying to achive by that...
I was just trying to convert the following methods that I wrote in C/C++ to Java. In short, the code provides a very efficient way of calculating the indices of the left-most and right-most bits of a number that are set to one. The two methods are based off of code in Knuth's Art of Computer programming, volume 4.
// Returns index of the left-most bit of x that is one in the binary
// expansion of x. Assumes x > 0 since otherwise lambda(x) is undefined.
// Can be used to calculate floor(log(x, 2)), the number of binary digits
// of x, minus one.
int lambda(unsigned long x) {
double y = (double) x;
// Excuse the monstrocity below. I need to have a long that has the raw
// bits of x in data. Simply (long)y would yield x back since C would cast
// the double to a long. So we need to cast it to a (void *) so that C
// "forgets" what kind of data we are dealing with, and then cast it to
// long.
unsigned long xx = *((long *)((void*)&y));
// The first 52 bits are the the significant. The rest are the sign and
// exponent. Since the number is assumed to be positive, we don't have to
// worry about the sign bit being 1 and can simply extract the exponent by
// shifting right 52 bits. The exponent is in "excess-1023" format so we
// must subtract 1023 after.
return (int)(xx >> 52) - 1023;
}
// Returns the index of the right-most one bit in the binary expansion of x
int rho(unsigned long x) {
return lambda(x & -x);
}
As you can see, I need to have a long that has the same bits of a double, but without a void* cast, I am not sure how to do this in Java. Any thoughts? Is it even possible?
There's a static function, doubleToLongBits(), to perform the type conversion.
long xx = Double.doubleToLongBits(y);
return (int) (xx >>> 52) - 1023;
Note the >>> treats the long as an unsigned value when shifting right.
Reading the commentary, though, it sounds like what you want is a simple function of the number of leading zeros.
return 63 - Long.numberOfLeadingZeros(x);
I would guess this is more efficient on most current architectures, but you'd have to profile it to be sure. There's a similar "trailing zeros" method to compute your rho() function.
I've been using images to store data, since editing binary data through Paint.net is much friendlier than most hex editors.
However, some of my data is long integers. Long integers are twice the size of a 32-bit integer in java, 64-bits. How does one get the long to two integers, and more importantly, back to a long when reading the image? Since Java does not have unsigned ints, the top bit of the integer or long is the negative sign bit, even though bit 32 (the lower integer/pixel) will be an ordinary bit in the long integer.
Most methods of converting long to int discard the upper bits, as well, which will or may contain bitwise (binary) information!
What I need to do is
Transform a single long into two integers that faithful contain its bit data
Transform two integers back into a long that faithfully contains their bit data.
No need to use Autoboxing (Long, Integer, etc.). Primitives work just fine. The following is the best you can do in the Java programming language.
Join
Combining two ints into a long
int lo; // Integer to fill lower bits
int hi; // Integer to fill upper bits
long val = (((long) hi) << 32) | (lo & 0xffffffffL);
Split
Retrieving the (upper) bits 31-16
int hi = (int) (val >> 32);
Retrieving the (lower) bits 15-0
int lo = (int) val;
Note:
Be aware of the difference between:
n >> 32 (Sign-extend right-shift)
n >>> 32 (Zero-fill right-shift)
Since Java used only signed bits, the >>> operator was introduced to handle integers as if they were "unsigned".
int u,v
long n = u;
if (v < 0) { ++n; }
n <<= 32;
n += v;
You'll either need to make two new longs with the same values or you can typecast the integers.
int x = 0;
(long) int x = 2;
This declares a new integer with a set value of 0 and then changes the value to 2 once it becomes a long.
Simple response, but i hope it helps
I have a long number and I want to manipulate it bits in following way:
Long l = "11000000011" (long l 's bit representation)
Long ll1 = "110000000" (remove last two bits from l and convert to Long)
Long ll2 = "11" (keep last two bit's of l and discard other bits and convert to Long)
Can anybody help me, how to do this in Java in a fast way ?
To convert a string of bits into a long, you can use Long.parseLong:
long l = Long.parseLong("11000000011", 2);
You can then use the bit-shifting operators >>, <<, and >>> to drop off the lower bits. For example:
long ll1 = l >>> 2;
To drop off all but the top two bits, you can use Long.bitCount to count the bits, then shift off the remaining bits.
long ll2 = l >>> (Long.bitCount(ll1) - 2);
EDIT: Since the question you're asking has to do with going from longs to the bits of the longs, you should use the Long.toBinaryString method for this:
String bits = Long.toBinaryString(/* value */);
From there, to drop off the last two bits you can use simple string manipulation. Try using String.substring for this.
Hope this helps!
long l = Long.parseLong("11110", 2) ;
long ll1 = l >>> 2;
long lb = (l & 1) ; last bit
long ls = l >>> 1;
long lb1 = (ls & 1) ; bit before last bit