Shifting a long by more than 31 bits (java) - java

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).

Related

Don't understand how these bitwise operators operate on bytes and integers

I am working with some code that takes in a binary file as input. However, I am having trouble understanding the for loop in the code, as I don't understand what the bitwise operators do to IFD_Address, such as the |=, <<, and & 0xff. I think IFD_Address refers to a pointer in the binary file, but I am not sure. What is this piece of code trying to achieve?
byte[] IFD_Address_tmp = Arrays.copyOfRange(bytes, 4, 8);
int IFD_Address = 0;
int i = 0;
int shiftBy = 0;
for (shiftBy = 0; shiftBy < 32; shiftBy += 8) {
IFD_Address |= ((long) (IFD_Address_tmp[i] & 0xff)) << shiftBy;
i++;
}
This behavior is best understood in terms of moving bits around, not numbers. Bytes comprise eight bits, integers, 32 bits. The loop basically takes each byte in the array and places the corresponding bits in the integer IFD_Address in 8-bit chunks, from right (least significant) to left (most significant), like this:
About the bitwise operations:
& 0xff is required to capture the 8 bits into an integer;
<< shifts the bits to the left to select the appropriate place in IFD_Address;
|= sets the bits in IFD_Address.
See this tutorial for details.

Java - Copy integer to long

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;

What does this binary documentation mean?

I'm trying to decode somebody's byte array and I'm stuck at this part:
&lt state &gt ::= "01" <i>(2 bits) for A</i>
"10" <i>(2 bits) for B</i>
"11" <i>(2 bits) for C</i>
I think this wants me to look at the next 2 bits of the next byte. Would that mean the least or most significant digits of the byte? I suppose I would just throw away the last 6 bits if it means the least significant?
I found this code for looking at the bits of a byte:
for (int i = 0; i < byteArray.Length; i++)
{
byte b = byteArray[i];
byte mask = 0x01;
for (int j = 0; j < 8; j++)
{
bool value = b & mask;
mask << 1;
}
}
Can someone expand on what this does exactly?
Just to give you a start:
To extract individual bits of a byte, you use "&", called the bitwise and operator. The bitwise and operation means "preserve all bits which are set on both sides". E.g. when you calculate the bitwise-and of two bytes, e.g. 00000011 & 00000010, then the result is 00000010, because only the bit at the second last position is set in both sides.
In java programming language, the very same example looks like this:
int a = 3;
int b = 2;
int bitwiseAndResult = a & b; // bitwiseAndResult will be equal to 2 after this
Now to examine if the n'th bit of some int is set, you can do this:
int intToExamine = ...;
if ((intToExamine >> n)) & 1 != 0) {
// here we know that the n'th bit was set
}
The >> is called the bitshift operator. It simply shifts the bits from left to right, like this: 00011010 >> 2 will have the result 00000110.
So from the above you can see that for extracting the n'th bit of some value, you first shift the n'th bit to position 0 (note that the first bit is bit 0, not bit 1), and then you use the bitwise and operator (&) to only keep that bit 0.
Here are some simple examples of bitwise and bit shift operators:
http://www.tutorialspoint.com/java/java_bitwise_operators_examples.htm

Get n Least Significant Bits from an Int

This seems fairly straightforward, but I cant find an answer. If I have an int X, what is the best way to get N least significant bits from this int, in Java?
This should work for all non-negative N < 33 32:
x & ((1 << N) - 1)
It's worth elaborating on how this works for N == 31 and N == 32. For N == 31, we get 1 << N == Integer.MIN_VALUE. When you subtract 1 from that, Java silently wraps around to Integer.MAX_VALUE, which is exactly what you need. For N == 32, the 1 bit is shifted completely out, so 1 << N == 0; then (1 << N) - 1 == -1, which is all 32 bits set.
For N == 32, this unfortunately doesn't work because (thanks, #zstring!) the << operator only shifts by the right side mod 32. Instead, if you want to avoid testing for that case specially, you could use:
x & ((int)(1L << N) - 1)
By shifting a long, you get the full 32-bit shift, which, after casting back to an int, gets you 0. Subtracting 1 gives you -1 and x & -1 is just x for any int value x (and x is the value of the lower 32 bits of x).
Ted's approach is likely to be faster but here is another approach
x << -N >>> -N
This shift all the bit up and then down to chop off the top bits.
int i = -1;
System.out.println(Integer.toBinaryString(i));
i = i << -5 >>> -5;
System.out.println(Integer.toBinaryString(i));
prints
11111111111111111111111111111111
11111
You can also use a mask. If you use the & bitwise operator you can then remove whatever bit you would want to remove (say the highest x bits);
int mask = 0x7FFFFFFF //Example mask where you will remove the
// most significant bit
// (0x7 = 0111b and 0xF = 1111b).
int result = numberToProcess & mask; //And apply the mask with the &bitwise op.
The disadvantage to this is that you will need to make a mask for each bit, so perhaps this is better seen as another method of approach in general.

Converting Little Endian to Big Endian

All,
I have been practicing coding problems online. Currently I am working on a problem statement Problems where we need to convert Big Endian <-> little endian. But I am not able to jot down the steps considering the example given as:
123456789 converts to 365779719
The logic I am considering is :
1 > Get the integer value (Since I am on Windows x86, the input is Little endian)
2 > Generate the hex representation of the same.
3 > Reverse the representation and generate the big endian integer value
But I am obviously missing something here.
Can anyone please guide me. I am coding in Java 1.5
Since a great part of writing software is about reusing existing solutions, the first thing should always be a look into the documentation for your language/library.
reverse = Integer.reverseBytes(x);
I don't know how efficient this function is, but for toggling lots of numbers, a ByteBuffer should offer decent performance.
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
...
int[] myArray = aFountOfIntegers();
ByteBuffer buffer = ByteBuffer.allocate(myArray.length*Integer.BYTES);
buffer.order(ByteOrder.LITTLE_ENDIAN);
for (int x:myArray) buffer.putInt(x);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.rewind();
int i=0;
for (int x:myArray) myArray[i++] = buffer.getInt(x);
As eversor pointed out in the comments, ByteBuffer.putInt() is an optional method, and may not be available on all Java implementations.
The DIY Approach
Stacker's answer is pretty neat, but it is possible to improve upon it.
reversed = (i&0xff)<<24 | (i&0xff00)<<8 | (i&0xff0000)>>8 | (i>>24)&0xff;
We can get rid of the parentheses by adapting the bitmasks. E. g., (a & 0xFF)<<8 is equivalent to a<<8 & 0xFF00. The rightmost parentheses were not necessary anyway.
reversed = i<<24 & 0xff000000 | i<<8 & 0xff0000 | i>>8 & 0xff00 | i>>24 & 0xff;
Since the left shift shifts in zero bits, the first mask is redundant. We can get rid of the rightmost mask by using the logical shift operator, which shifts in only zero bits.
reversed = i<<24 | i>>8 & 0xff00 | i<<8 & 0xff0000 | i>>>24;
Operator precedence here, the gritty details on shift operators are in the Java Language Specification
Check this out
int little2big(int i) {
return (i&0xff)<<24 | (i&0xff00)<<8 | (i&0xff0000)>>8 | (i>>24)&0xff;
}
The thing you need to realize is that endian swaps deal with the bytes that represent the integer. So the 4 byte number 27 looks like 0x0000001B. To convert that number, it needs to go to 0x1B000000... With your example, the hex representation of 123456789 is 0x075BCD15 which needs to go to 0x15CD5B07 or in decimal form 365779719.
The function Stacker posted is moving those bytes around by bit shifting them; more specifically, the statement i&0xff takes the lowest byte from i, the << 24 then moves it up 24 bits, so from positions 1-8 to 25-32. So on through each part of the expression.
For example code, take a look at this utility.
Java primitive wrapper classes support byte reversing since 1.5 using reverseBytes method.
Short.reverseBytes(short i)
Integer.reverseBytes(int i)
Long.reverseBytes(long i)
Just a contribution for those who are looking for this answer in 2018.
I think this can also help:
int littleToBig(int i)
{
int b0,b1,b2,b3;
b0 = (i&0x000000ff)>>0;
b1 = (i&0x0000ff00)>>8;
b2 = (i&0x00ff0000)>>16;
b3 = (i&0xff000000)>>24;
return ((b0<<24)|(b1<<16)|(b2<<8)|(b3<<0));
}
Just use the static function (reverseBytes(int i)) in java which is under Integer Wrapper class
Integer i=Integer.reverseBytes(123456789);
System.out.println(i);
output:
365779719
the following method reverses the order of bits in a byte value:
public static byte reverseBitOrder(byte b) {
int converted = 0x00;
converted ^= (b & 0b1000_0000) >> 7;
converted ^= (b & 0b0100_0000) >> 5;
converted ^= (b & 0b0010_0000) >> 3;
converted ^= (b & 0b0001_0000) >> 1;
converted ^= (b & 0b0000_1000) << 1;
converted ^= (b & 0b0000_0100) << 3;
converted ^= (b & 0b0000_0010) << 5;
converted ^= (b & 0b0000_0001) << 7;
return (byte) (converted & 0xFF);
}

Categories