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
Related
If I want to set the 37th bit of a long to 1, I believe my code would look something like this:
long l = 0;
l |= 0b1 << 37;
However, this doesn't work because a long cannot shift by more than 31 bits. This confuses me because Oracle documentation says longs are 64 bit. (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html)
I have taken a look at How do I bit shift a long by more than 32 bits?, but this seems to only work of c/c++.
I want to be able to toggle bits for a data type that has 64 bits. How would I do that in java?
long l;
l = 0;
l |= 0b1 << 37;
System.out.println(l);
// Outputs 32
l = 0;
l |= 0b1L << 37;
System.out.println(l);
// Outputs 137438953472
The problem you're running into is that your operation breaks down like this:
l |= 0b1 << 37;
Turns into, in sequence:
int _temp = 1 << 37;
l |= (long) _temp;
The reason it's like that is because 0b1, or any numeric literal that lacks a decimal part and a trailing letter to indicate what kind of literal you want (D/F/L for double/float/long), is therefore an int, period. You then left-shift this int value (1; 0b1 is just a weird way to write 1 after all) by 37. The spec of left-shift states that the right-hand operator of a shift operation only considers the lower 5 bits for int shifts and the lower 6 for long shifts. Because otherwise you'd just be making the value 0. Thus, someInt << 37 is a weird way of writing someInt << 5.
The solution is to make sure that your shift operation is actually happening on longs. There are many, many ways to make that happen.
Use a long literal
By writing a trailing L. It can be written in either case, but style guides and developers will egg your house if you use a lowercase l because duh that is incredibly stupid, don't do that. It looks like a 1. Thus:
l |= 1L << 37; // or if you must, 0b1L works too
One step at a time.
long temp = 1;
temp <<= 37;
l |= temp;
Cast it
l |= ((long) 0b1) << 37;
These will all get the job done: They all end up having the << operation be in 'long mode' (which occurs if the LHS is of type long, which it is, in all these 3 examples).
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;
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 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;
Consider the following JAVA statement:
System.out.println(3232235776l & 0xFFFFFFFE);
The output is: 3232235776
When I re-write the statement in JavaScript:
console.log(3232235776 & 0xFFFFFFFE);
The output is: -1062731520
Q. Is there a way to work around this overflow in JavaScript and get the right output?
For the sake of simplicity, I did not post the function I was converting from Java. Here it is. Please assume ipToLong and longToIp as working blackboxes in both Java and JavaScript (i.e. they do the right ip to long int conversion and vice-versa correctly, in both Java and JS, linted and unit tested).
Taken from here: https://stackoverflow.com/a/5032908/504674
Now, can someone help me convert the below Java line to JavaScript correctly?
Specifically: long maskedBase = start & mask;.
Full function to be converted:
public static List<String> range2cidrlist( String startIp, String endIp ) {
int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000,
0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,
0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800,
0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,
0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
0xFFFFFFFF
};
long start = ipToLong(startIp);
long end = ipToLong(endIp);
ArrayList<String> pairs = new ArrayList<String>();
while ( end >= start ) {
byte maxsize = 32;
while ( maxsize > 0) {
long mask = CIDR2MASK[maxsize -1];
long maskedBase = start & mask;
if ( maskedBase != start ) {
break;
}
maxsize--;
}
double x = Math.log( end - start + 1) / Math.log( 2 );
byte maxdiff = (byte)( 32 - Math.floor( x ) );
if ( maxsize < maxdiff) {
maxsize = maxdiff;
}
String ip = longToIp(start);
pairs.add( ip + "/" + maxsize);
start += Math.pow( 2, (32 - maxsize) );
}
return pairs;
}
Instead of using & to remove the bit you want, you could subtract it.
long n = 3232235776L;
System.out.println(n - (n & 1)); // instead of 1 you can use ~0xFFFFFFFE
This shouldn't suffer from an overflow in your case.
Bitwise operators treat their operands as a sequence of 32 bits (zeros and ones)
says the Mozilla documentation.
You start out with a floating point value, it is converted to a 32 bit value. But because it's too big, it will overflow.
I suggest you try the following instead:
var number = 3232235776;
if (number % 2 == 1) {
number = number - 1;
}
Of course, you could write this more succinctly, but also more cryptic:
var number = 3232235776;
number = number - (number % 2);
That should be semantically equivalent for both positive and negative numbers.
Sign extension
In Java, 0xFFFFFFFE is a 32bit integer representing -2 when ANDing this with a long, it gets converted to a 64bit integer: 0xFFFF_FFFF_FFFF_FFFE, so all this effectively does is clear the last bit, i.e. round down (down, not towards zero).
I'm not sure if that's what you wanted. If it is intended, it's probably not something I would like in my codebase.
No sign extension
Here is the equivalent JavaScript code, if you intended this to happen without sign extension:
var number = 3232235776;
if (number % 2 == 1) {
number = number - 1;
}
number = number % 0x100000000; // That's 8 zeroes, i.e. keep the last 4 bytes