I have cracked my head enough and hence asking here:
This works:
int dummy_1, dummy_2;
long final_dummy;
dummy_1 = 0x12345678;
dummy_2 = 0x78563412;
final_dummy = (long)dummy_1 | (long)dummy_2<<32;
System.out.println(String.format("%08X", final_dummy));
Answer : 7856341212345678
This doesnt work:
int dummy_1, dummy_2;
long final_dummy;
dummy_1 = 0xB6F93000;
dummy_2 = 0xB6F93000;
final_dummy = (long)dummy_1 | (long)dummy_2<<32;
System.out.println(String.format("%08X", final_dummy));
Answer: FFFFFFFFB6F93000
Expected answer : B6F93000B6F93000
0xB6F93000 is actually the int value -1225183232. When coerced to long, it becomes 0xFFFFFFFFB6F93000L, which is also -1225183232.
When you convert int to long you need to make it an unsigned conversion.
// In Java 8
int dummy_1 = 0xB6F93000;
int dummy_2 = 0xB6F93000;
long final_dummy = Integer.toUnsignedLong(dummy_1) | Integer.toUnsignedLong(dummy_2) << 32;
// In all Java versions
int dummy_1 = 0xB6F93000;
int dummy_2 = 0xB6F93000;
long final_dummy = (dummy_1 & 0xFFFFFFFFL) | (long)dummy_2 << 32;
In the code that doesn't work, your initial dummy_1 and dummy_2 values are negative; in Java, all numeric types are signed. The highest bit is set, which is seen because the first hex digit is greater than or equal to 8.
Because these values are negative, when casted to a long, sign extension occurs.
0xB6F93000 => 0xFFFFFFFFB6F9000L
When logically ORed, those F digits remain, explaining why the most significant 8 hex digits (4 bytes) are Fs instead of your value.
Use a mask to clear those sign-extended bits prior to ORing them.
final_dummy = (((long) dummy_1) & 0xFFFFFFFFL) | (((long)dummy_2) & 0xFFFFFFFFL) << 32;
This will clear the most significant 8 hex digits, as if sign extension did not take place. With this change, I get:
B6F93000B6F93000
Bit-anding on dummy_2 is not necessary, because the shift eliminates those 32 bits anyway.
final_dummy = (((long) dummy_1) & 0xFFFFFFFFL) | (long) dummy_2 << 32;
As an aside, normal Java naming conventions dictate that the variables names should be dummy1, dummy2, and finalDummy.
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;
Given a long with bytes WXYZ (where each letter is a byte), I would like some fast bit twiddling code that will create two longs with the same bytes as the original, but interleaved with the 0 byte.
For example, given the long with value ABCDEFGH (each letter being one byte), produce the two longs:
0A0B0C0D
0E0F0G0H
Something equivalent to, but faster than:
long result1 = expand((int)(input >>> 32));
long result2 = expand((int)input);
long expand(int inputInt) {
long input = intputInt;
return
(input & 0x000000FF) |
(input & 0x0000FF00) << 8 |
(input & 0x00FF0000) << 16 |
(input & 0xFF000000) << 24;
}
The following is about 25% faster for me (Java 7, benchmarked using Google Caliper), YMMV may vary according to your compiler of course:
long a = (input | (input << 16));
long result = (a & 0xFF000000FFL) + ((a & 0xFF000000FF00L) <<8);
The idea is to use a bit of extra parallelism vs. the original approach.
The first line is a neat trick that produces garbage in bits 17-32, but you don't care as you are going to mask it out anyway. :-)
long expand(int inputInt) {
long input = intputInt;
return
(input & 0x000000FF) << 8 |
(input & 0x0000FF00) << 16 |
(input & 0x00FF0000) << 24 |
(input & 0xFF000000) << 32;
}
In C++ you could try to use a union:
typedef union
{
char bytes[8];
long value;
} PlatformSpecificSolution;
long expand(int valueInt)
{
PlatformSpecificSolution pss;
pss.value = valueInt;
pss.bytes[6] = pss.bytes[3]; pss.bytes[3] = 0;
pss.bytes[4] = pss.bytes[2]; pss.bytes[2] = 0;
pss.bytes[2] = pss.bytes[1]; pss.bytes[1] = 0;
// pss.bytes[0] = pss.bytes[0];
return pss.value;
}
I have no idea if this is faster (you will have to run benchmarks on the platforms that you want to support). This solution is definitely more error prone. You should always ask yourself, if the performance benefit outways the disadvantage of less maintainable code.
I am finding it difficult to understand and work with this binary representation in java:
With the help of the user Jon Skeet, I understood that binary representation should be built this way.
Here's a code sample:
public class chack {
public static void main(String[] args) {
int num2=2;
int num3=3;
int num4=4;
int num1=1;
int nirbinary = (num1 << 24) | (num2 << 16) | (num3 << 8) | num4;
System.out.println(nirbinary);
String nir= Integer.toBinaryString(nirbinary);
System.out.println(nir);
}
}
Couple of question:
How does one get num1 (for example) back from an int who is already in this binary
why do I get 16909060 when I print nirbinary- what does it stands for?
How does one get num1 (for example) back from an int who is already in this binary
representation?
Thank you
I am not completely sure what you are missing, so I will just explain how you can convert integers to binary strings back and forth in java.
You can get a binary string from an integer like so:
int i = 1234;
String binString = Integer.toBinaryString(i);
and you can convert the string back to an integer this way:
int iNew = Integer.parseInt(binString, 2);
Note the second argument to Integer.parseInt() is the desired base of the number. 2 is binary, 8 is octal, 10 decimal, etc.
16909060 stands for the number 16909060.
It is (1 * 224) + (2 * 216) + (3 * 28) + 4.
To get num1 back out, just right-shift the result the same amount you left-shifted and mask out the other bytes (not always necessary for num1(*), but for the others):
int num1 = nirbinary >> 24 & 0xFF;
int num2 = nirbinary >> 16 & 0xFF;
int num3 = nirbinary >> 8 & 0xFF;
int num4 = nirbinary & 0xFF;
Note that nirbinary is not "a binary representation". Or more precisely: it's no more or less binary than num1, num2, num3 and num4: internally all numbers (and characters, and booleans, ...) are stored in binary.
(*) note that if num1 is > 127, then you either need to use >>> to do the right-shift or use the & 0xFF in order to ensure that the correct value is restored. The difference between >> and >>> are the "new" bits inserted on the "left" side of the value: With >> they will depend on the highest-value bit (known as sign-extension) and with >>> they will always be 0.
Every int is a number, it's not binary, hex or decimal, it's just a number. the statement (num1 << 24) | (num2 << 16) | (num3 << 8) | num4; is a binary manipulation of 4 ints into another int. It doesn't change the representation of nirbinary to binary, since nirbinary has no representation, because (again) it's just a number.
Integer.toBinaryString(nirbinary) returns the binary representation of nirbinary which means "how would nibinary look like in base-2".
If you have a String which is a binary representation of a number, you could get its value, by using Integer.parseint(yourbinaryrepresentation, yourbase); for example - Integer.parseint(nir, 2);
And another thing:
You can't always get back one of the numbers back from nirbinary, since you performed a bit manipulation that is not reversible, for example:
int i1 = 5; //binary 0101
int i2 = 4; //binary 0100
int i3 = i1 | i2; //binary 0101
you cannot recognize each of your variables (i1, i2) since they have a common bit, i3 could have been the result of or on two other numbers:
int i1 = 1; //binary 0101
int i2 = 4; //binary 0100
int i3 = i1 | i2; //binary 0101
in your case, if each number is smaller than 256, you can reverse it with the following operation:
int myoldnumber = (nirbinary >> previousShift) & 0xff;
for example, to retrieve num1 you can do:
int retrievedNum1 = (nirbinary >> 24) & 0xff;
Here no need to depend only on binary or any other format...
one flexible built in function is available
That prints whichever format you want in your program..
Integer.toString(int,representation);
Integer.toString(100,8) // prints 144 --octal representation
Integer.toString(100,2) // prints 1100100 --binary representation
Integer.toString(100,16) //prints 64 --Hex representation
Integer.toString(100,5) // prints 400 --Base 5
When working with bitshifting and integers I would recommend you think in hexadecimal numbers, that will usually make life a lot easier. Just keep in mind that 8 bits represent 1 byte and 1 byte covers the hex-range from 0x00 to 0xFF
Since num1 to num4 are smaller than 10, their decimal representation is equal to their hex representiation, ie 1 = 0x01, 2 = 0x02 etc..
As I told you: 1 Byte is 8 bits. In your bitshifting operation you always shift multiple of 8.
So 0x01 << 8 => 0x0100
0x01 << 16 => 0x010000
etc.
So you basically only add zero bytes, which of course increases the value.
What you do next is to | them, a bitwise or. This means that two bitfields get modified in such a way that the result has a 1 at one place if at least one of the input values as a 1 there. Since your shifted ints contain only zero at the back, a bitwise or is nothing else then to put the value in this spot.
E.g:
(0x01 << 8) | 0x02
0x01 << 8 will produce 0x0100. Now you simply have to replace the last 00 with 02, since you or them: 0x0102
If you want to recreate the original int, you have to mask the part that int represents (this is easy since the parts do not overlap in your example) and then shift it back.
E.g.
Say ou produced 0x010203 and want to have only 0x02. You now have to mask shift it back 0x010203 >> 8 which will put the 02 in the last part. Now simply mask this last part 0x0102 && 0xFF. This will set all but the last 8 bits to zero
it's basically 1 * 2^24 + 2 * 2^16 + 3 * 2^8 + 4 = 16909060
You can get num1 by doing num1 = nirbinary >> 24.
What did you expect instead?
To get the most significant byte from an int i:
(i >> 24) & 0xff
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);
}
I have a long and a short
I want the bits from the short to overwrite the low order 16 bits of the long.
Ex (broken into 16bit chunks for readability):
> long = 0xffff 0xffff 0xffff 0xffff
> short= 0x1234
>
> output = (long)0xffff 0xffff 0xffff 0x1234
static long foobar(long aLong, short aShort) {
return aLong & 0xFFFFFFFFFFFF0000L | aShort & 0xFFFFL;
}
Note that you must AND the short value with 0xFFFFL here, otherwise sign extension will cause the code to break (all high bits in the result will be set, regardless of their original value in the long) if the short is greater than or equal to 0x8000.
long l = ...;
short s = ...;
long n = (l & ~0xFFFF) | (s & 0xFFFFL);