wrong result from left shift in java - java

I have made a variable in java, byte a = 0xA6; //10100110
then I made this :
System.out.println(Integer.toHexString( ((short)a<<8)&0xFFFF ));
The result is 0xA600. This is the right result. But when i tried
System.out.println(Integer.toHexString( ((short)a<<3)&0xFFFF ));
The expected result should be : 0x530 (10100110000)
but I got 0xFD30(1111110100110000) Emm... Can somebody explain how I got that wrong result...??
thanks... :-)

The byte value A6 represents a negative number (bytes are signed in Java). When you cast to a short it gets sign extended to FFA6. Moreover the shift operation is executed with integer values so it is again sign extended to FFFFFFA6. Shift left by three bits gives FFFFFD30 and taking the lower 16 bits gives 0000FD30.
This does not matter if you shift by 8 bits because you shift out and mask the additional 1 bits.

When you declare initialize byte variable you have to downcast it from integer:
byte a = (byte) 0xA6;
So, instead of 10100110 you've got 11111111111111111111111110100110.
And, beacuse of this left shift works in that way:
((short)a<<8)&0xFFFF
returns 1010011000000000
((short)a<<3)&0xFFFF
returns 1111110100110000

Related

Shifting negative BigInteger value - Java

I am trying to shift a 7 byte array to the right by 7 bits.
To do this, I am using BigInteger's shiftright method. However, when shifting right for negative BigIntegers, padding with 1s are added or sometimes the leading bit is removed.
Here is the following bit of code doing the shifting:
byte[] vcwManD = decryptedVCW;
BigInteger bigIntD = new BigInteger(vcwManD); // create big int array for shift
BigInteger shiftIntD= bigIntD.shiftRight(7); // shift right 7 bits
vcwManD = shiftIntD.toByteArray();
For a byte array E865037A9C6424 in binary:
11101000011001010000001101111010100111000110010000100100
When shifted I get D0CA06F538C8 in binary:
110100001100101000000110111101010011100011001000
As you can see, it has shifted 7 bits to the right, however the leading bit has been stripped.
Another issue is the 1 padding. For byte array 90998951A37908 in binary
10010000100110011000100101010001101000110111100100001000
produces FF213312A346F2 in binary:
11111111001000010011001100010010101000110100011011110010
This time around 7 1's have been padded at the start.
Does anyone know how to solve this issue?
Many thanks
Shiv
If you are doing bit shifts you are likely working with a long unsigned value rather than signed value. So when you create your BigInteger use this constructor:
new BigInteger(1, vcwManD);
That way you are guaranteed to have a positive number and you should be able to shift it around with no consequence.
Negative numbers are stored in memory using two's complement. This means that if the number is negative, the first bit will be 1. When you bit shift a negative number to the right, it must remain negative, so the newly introduced values will be 1's.

Valid way to move bits in java

I'm working on an assignment for school and I'm getting strange output. So, I figured I should start checking some of my more basic methods before I get to the fancier ones. The question I have is this:
would the method
public static short get16(byte a, byte b){
return (short)(a*Math.pow(2,8)+b)
}
return a short where the first 8 bits are byte a and the last 8 bits are byte b?
I don't see why it wouldn't, since multiplying by 2^8 would be the same as left shifting 8 bits to the left. And adding the second byte would make up for the 8 0's achieved by multiplying by 2^8. Is this correct?
I wouldn't recommend using Math.pow to compute 256. pow is notoriously hard to implement correctly; some extant implementations don't even get the exact cases right!
Also, bytes in Java are signed, so you probably want to say (a&255) and (b&255) rather than just a and b. Sign extension will ruin everything for you.
Some things you should know:
"Math.pow" is a floating-point function. Don't do integer calculation by calling floating-point functions and then rounding the result.
Java virtual machine is internally a 32-bit system. All "byte" and "short" mathematical expressions are internally evaluated as "int". Even an addition of two bytes goes internallly like this: 1) convert the bytes to ints, 2) add the ints, 3) convert the lower 8 bits to byte.
The correct way is:
return (short) ((a << 8) + (b & 255));
or
return (short) ((a << 8) | (b & 255));
When "byte" is converted to "int", the sign bit gets copied into the new bits. For example 0b01010101 becomes 0b00000000_00000000_00000000_01010101, because the first bit was 0, but 0b10101010 becomes 0b11111111_11111111_11111111_10101010.

Java bitmask range

I need to extract an exact range of bits from an existing long, specifically I need bits 51:12 from a 64 bit value.
The value is:
0x0000000415B2C01E
So the value of bits 51:12 should be:
0x0000415B2C
I'm a bit confused as to how to actually extract that range, or any range for that matter. I've been told to simply left shift by 12 (value << 12) to obtain the bits I need, but that gives me the value of:
0x415B2C01E000
Now I might be completely misunderstanding how bit shifting works, but I can't get my head around how to extract bit ranges. I've found a lot of existing stuff on it, but I'm even more confused about it all now.
If anyone could help me out, it would certainly be appreciated.
Thanks
Shift and mask:
answer = value >> 12 & 0xFFFFFFFFFFF;

Declaring masks for bitwise operations

I'm new to low level operations like this, I'm hoping someone can point out the obvious mistake I must be making here.
//Input value - 00111100
//I want to get the value of the bits at indexes 1-3 i.e 0111.
byte mask = (byte)0x00001111; // This gives 17 not the 15 I'd expect
byte shifted = (byte)(headerByte >> 3);
//shifted is 7 as expected
byte frameSizeValue = (byte)(shifted & mask); //Gives 1 not 7
It looks like the problem lies with the way the mask is defined, but I can't see how to fix it.
First of all 0x00001111 is in hex, which is a larger number than 255 - 16^3 + 16^2 + 16 + 1 = 4369 and byte overflows. Look here how to represent binary numbers or just use shifted & 15.
Your mask needs to be binary 00001111, which is equal to hex 0x0F.
byte mask = (byte)0x0F;
With java 7 you can create binary literals
byte binaryLit = (byte)0b00001111;
0xsomenumbers is a hex literal, and pre java7 there is no support for binaries.
You say you want to mask the first three bits but as Petar says, 0x001111 are not bits. If you want to mask the three bits you need to mask with 7

Sign(+/-) error in byte in Java byte setting operations

I am declearing in Java
public byte[] orbits = new byte[38];
Now if I am doing
orbits[24] = (byte)0xFF;
orbits[24] should get populated by 11111111 i.e FF(in hexadecimal) but instead its getting populated with -1.
This operation in C++ working perfectly
char orbits[38]
orbits[24] = (char)0xFF;
How to replicate the similar situation in Java using byte?
Thanks
Well, it just happens that -1 is 0xFF. Everything is correct. byte stores values from -128 to 127 using two's complement.
In Java there are no unsigned types. If you want to use bit patterns, then use byte. 0xFF and -1 are the same thing in this situation. If you want to use numbers, that is, 0xFF is actually 255 and not -1, then you need to use a bigger type, like short.

Categories