How is 0x80000000 equated to -2147483648 in java? - java

Taking the binary of 0x80000000 we get
1000 0000 0000 0000 0000 0000 0000 0000
How does this equate to -2147483648. I got this question with this program.
class a
{
public static void main(String[] args)
{
int a = 0x80000000;
System.out.printf("%x %d\n",a,a);
}
}
meow#VikkyHacks:~/Arena/java$ java a
80000000 -2147483648
EDIT I learned that 2's complement is used to represent negative numbers. When I try to equate this with that 1's complement would be
1's Comp. :: 0111 1111 1111 1111 1111 1111 1111 1111
2's Comp. :: 1000 0000 0000 0000 0000 0000 0000 0000
which again does not make any sense, How does 0x80000000 equate to -2147483648

This is what happens with signed integer overflow, basically.
It's simpler to take byte as an example. A byte value is always in the range -128 to 127 (inclusive). So if you have a value of 127 (which is 0x7f) if you add 1, you get -128. That's also what you get if you cast 128 (0x80) to byte:
int x = 0x80; // 128
byte y = (byte) x; // -128
Overflow (in 2s complement integer representations) always goes from the highest expressible number to the lowest one.
For unsigned types, the highest value overflows to 0 (which is again the lowest expressible number). This is harder to show in Java as the only unsigned type is char:
char x = (char) 0xffff;
x++;
System.out.println((int) x); // 0

This is the case when there is overflow, with respect to the range of a data type.
Here is an example that I can share.
int number = 0x80; // 0x80 is hexadecimal for 128 (decimal)
byte castedNumber = (byte)(number); // On casting, there is overflow,as byte ranges from -128 to 127 (inclusive).
System.out.println(castedNumber); //Output is -128.

Integer range for java is -2,147,483,648 to 2,147,483,647
The given is hex val 0x80000000 its equivalent decimal value is 2,147,483,648(1's complement conversion).
You can see the decimal value is not fit within the range which is called Integer overflow. Whenever overflow happens it circles itself to the other end in this case -2,147,483,648.

Related

XOR signed bytes in java

I'm new to Java and I am really confused about signed byte in Java.
byte a = -128;
byte b = 126;
System.out.println((byte)(a ^ b));
The output is -2. Can someone please explain why we get this? Is -2 the correct result for -128 XOR 126?
Another question is I have a byte b and I want it to XOR all possible bytes, my code is
byte i = -128
while (i <= 127) {
byte c = (byte) b ^ i;
i++;
}
Is it correct?
This about the representation of signed numbers in computers. They are represented as 2s-complement. This means:
126 = 0111 1110
-128 = 1000 0000
-2 = 1111 1110
Negative values in 2s-complement are formed by taking the absolute value as binary number, inverting all bits except the MSB, adding one to the result and setting the MSB which is used as sign-bit to 1, eg.:
-3:
0000 0011 absolute value (3)
0111 1100 invert all bits except MSB
0111 1101 add 1
1111 1101 set MSB to 1
binary math is pretty straight forward...
-128 in 8 bits is 10000000 (dont forget is 2 complement)
126 in 8 bits is 01111110
xor those then you get 1111 1110: which is -2 in 8 bits 2 complement

How to get a 14 bit, two's complement value into an Integer or Short and maintain the sign in Java

I have a 14 bit, two's complement value being sent to my java application form a bluetooth device in the form of a byte array.
I am unable to change the format of the data sent from the bluetooth device.
How do I get this value into an Integer or Short and maintain the sign?
A few things I have tried are
Short x = ByteBuffer.wrap(value).getShort();
Integer x = (short)(value[3] & 0xff) | (short)((value[2] << 8) & 0xff00);
The problem I think I encounter with the above code is when I receive a negative number, for example
-8192 (in two's complement 10 0000 0000 0000)
Because the receiving data type is 16 bits it expects the bit that negates the value to be 16 along but seen as what it actually receives is
0010 0000 0000 0000
It considers this 8192 and not -8192.
Simply extract the number from the byte array, ignoring signedness and excess bits completely:
byte[] data = ...
int rawNum = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
Now left shift the raw value by (type size - number of valid bits) then right shift using the signed shift operator
int realNum = (rawNum << (32 - 14)) >> (32 - 14);
This will first move the sign bit into the sign bit of the type storing the value (here: int) by shifting left, then when right shifting the sign bit is replicated shift-distance times (as defined by the shift operator).
I've generated a small example that uses integers, It should be easy to put the short you've retrieved in the integer. I've shown an example using your value variable just to be sure.
/**
* Expects the value to contain a 2-complement number stored in the
* least significant bits.
* The contents of the most significant bits is ignored.
* #param value the value to convert
* #param bitSize the size of the 2 complement number in the value
* #return the converted value
*/
public static int fromTwoComplement(int value, int bitSize) {
int shift = Integer.SIZE - bitSize;
// shift sign into position
int result = value << shift;
// Java right shift uses sign extension, but only works on integers or longs
result = result >> shift;
return result;
}
public static void main(String[] args) {
System.out.println(fromTwoComplement(0b00_00_0000_0000_0001, 14));
System.out.println(fromTwoComplement(0b00_01_1111_1111_1111, 14));
System.out.println(fromTwoComplement(0b00_10_0000_0000_0000, 14));
System.out.println(fromTwoComplement(0b00_11_1111_1111_1111, 14));
// largest negative
byte[] value = new byte[] { 0b0010_0000, 0b0000_0000 };
System.out.println(fromTwoComplement((int) ByteBuffer.wrap(value).getShort(), 14));
}
You should extend the most significant bit to the left.
Offhand: short y = (short)((x & 0b10000000000000 ) > 0 ? ( x | 0b1100000000000000 ) : x);
That is, if the most significant bit (for a 14 bit number) is 1, then the result of the & is going to be non-zero. If so, add the two additional ones to the left with an or. Otherwise leave as is.
public static void main(String[] args)
{
System.out.println((short) 0x1FFF);
// 0001 1111 1111 1111 - maximum positive value
System.out.println((short) 0x3FFF);
// 0011 1111 1111 1111 - minimum negative value
System.out.println((short) 0xF);
// 0000 0000 0000 1111 - positive 15
System.out.println((short) 0x3FF1);
// 0011 1111 1111 0001 - negative 15
System.out.println(convert14bit((short) 0x3FFF)); // returns -1
System.out.println(convert14bit((short) 0x3FF1)); // returns -15
}
public static final short convert14bit(short value)
{
if ((value & 0x2000) > 0)
{
// negative number
return (short) (value | 0xE000);
}
else
{
return value;
}
}

Why Integer.toBinaryString returns 32 bits if the argument is negative?

I was just messing around the Integer.toBinaryString(int) method.
When I pass a positive number say 7, it outputs 111 but when I pass negative 7, it outputs 11111111111111111111111111111001. I understand that Java uses 2's complement to represent negative numbers, but why 32 bits (I also know that an int is 32 bits long but doesn't fit in the answer)?
Ok so I did some digging...
I wrote up a little program probably close to what you did.
public class IntTest {
public static void main(String[] args){
int a = 7;
int b = -7;
System.out.println(Integer.toBinaryString(a));
System.out.println(Integer.toBinaryString(b));
}
}
My output:
111
11111111111111111111111111111001
So 111 is the same if it had 29 "0"s in front of it. That is just wasted space and time.
If we follow the instructions for twos compliment from this guy here you can see that what we must do is flip the bits ( zeros become ones and ones become zeros ) then we add 1 to the result.
So 0000 0000 0000 0000 0000 0000 0000 0111 becomes 1111 1111 1111 1111 1111 1111 1111 1001
The ones can not be thrown out because they are significant in the twos compliment representation. This is why you have 32 bits in the second case.
Hope this helps! -- Code on!!!
Because Java ints are signed 32-bit. If you use a negative number the first bit must be 1.
System.out.println(Integer.toBinaryString(0));
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE)); // 31 bits
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE - 1)); // 31 bits
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE + 1)); // 32 bits
System.out.println(Integer.SIZE);
Output is
0
1111111111111111111111111111111
1111111111111111111111111111110
10000000000000000000000000000000
32
Note that Integer.MAX_VALUE + 1 is Integer.MIN_VALUE (and it has an extra bit).
It outputs the smallest number it can, stripping leading zeroes. In the case of a negative number, the first bit of the 32 bits is a sign bit (i.e. -1 is 1, 30 zeros, and another 1). So, since it has to output the sign bit (it's significant), it outputs all 32 bits.
Here's a cool semi-relevant example of using the sign bit and the unsigned shift operator :). If you do:
int x = {positive_value};
int y = {other_positive_value};
int avg = (x + y) >>> 1;
The x and y integers can both use the first 31 bits since the 32nd bit is the sign. This way, if they overflow, they overflow into the sign bit and make the value negative. The >>> is an unsigned shift operator which shifts the value back one bit to the right which is effectively a divide by two and floor operation, which gives a proper average.
If you, on the other hand, had done:
int x = {value};
int y = {other_value};
int avg = (x + y) / 2;
And you had gotten an overflow, you would end up with the wrong result as you'd be dividing a negative value by 2.

Java left shift and fill with Zeros

I want to do left shifting but filling with zero, just like
int number = 20 >>> 10 = ( 0000 0000 0000 0000 0000 0000 0001 0100 )
int number = 20 >>> 32‎ = ( 0000 0000 0000 0000 0000 0000 0000 0000 )
I want to do the same with left shift, since there is no operator <<< for leftshift
int number = 20 << 32 = 0000 0000 0000 0000 0000 0000 0001 0100 ;
I want to fill it with zeros just like >>> operator. So how I can do this?
The << left shift operator will bring in zeros just as you want to.
The reason why there are 2 right shift operators (>> and >>>) is because in 2's complement form negative numbers have a bit value of 1 in the left-most bit position. The right shift operator >> will add the sign bit (1 in case of negative numbers, and 0 in case of positive numbers or zero) on the left side while the other (>>>) will always add zeros.
Both right shift operators have their use.
The language specification states that if bit shifting operators are applied on int since it is 32-bit long, only the 5 lowest bit is used to determine how many times to shift the number.
So if you shift by 32 which is 100000 in binary, it is equivalent to shift by 0 which means not to shift! And if you want to shift a 64-bit long, the 6 lowest bit is used only to tell how many times to shift.
You need to use long type and only make use of lowest 32 bits.
Use and operator to accomplish that.
long intMask = 0x00000000FFFFFFFFL;
long x = 0x00000000FFFFFFFFL;
x = x<<32;
int xi = (int)(x & intMask);
System.out.println("xi=" + xi); //Result will be 0
See question : Declaring an unsigned int in Java

Changing a bit within a byte in java

So I understand how to change an individual bit within a byte, what I am not sure is why my particular code is not working.
public static void setBit(byte[] input, int position, int value) {
int byteLocation = position / 8;
int bitLocation = position % 8;
byte tempByte = input[byteLocation];
if (value == 0)
tempByte = (byte) (tempByte & ~(1 << bitLocation));
else
tempByte = (byte) (tempByte | (1 << bitLocation));
input[byteLocation] = tempByte;
}
Now I have been testing it with the string "Testing1" which is 64bits long, then attempting to set the bits and display the value. It works a treat up to 46 bits, then on the 47th bit if I attempt to set it to 1 it borks up, works fine with 0 however.
Can't see the error in my ways, here's how I am testing it
String test = "Testing1";
byte[] bytes = test.getBytes();
for (int i = 0; i < bytes.length; i++)
System.out.print(String.format("%8s", Integer.toBinaryString(bytes[i])).replace(' ', '0') + "[" + i + "] ");
setBit(bytes, 44, 1);
System.out.println();
for (int i = 0; i < bytes.length; i++)
System.out.print(String.format("%8s", Integer.toBinaryString(bytes[i])).replace(' ', '0') + "[" + i + "] ");
The following is the output when I attempt to change the 47th bit to a 1
01010100[0] 01100101[1] 01110011[2] 01110100[3] 01101001[4] 01101110[5] 01100111[6] 00110001[7]
01010100[0] 01100101[1] 01110011[2] 01110100[3] 01101001[4] 11111111111111111111111111101110[5] 01100111[6] 00110001[7]
Change formatting as
Integer.toBinaryString(0xFF & bytes[i])
byte needs to be masked off because it is sign-extended, not zero-extended, to 32-bit int
The problem is you are setting the sign bit in the byte in question. So, that byte now has a negative value. You call Integer.toBinaryString(), which takes an int as it's argument, not a byte. The byte get promoted to an int, and it correctly evaluates the value of:
11101110
to it's equivalent integer:
11111111111111111111111111101110
I made your method smaller using ^ (xor)
public static void setBit(byte[] input, int position, int value) {
int byteLocation = position / 8;
int bitLocation = position % 8;
input[byteLocation] = (byte) (input[byteLocation] ^ (byte) (1 << bitLocation));
}
I haven't looked at it in too much detail but I think the problem with the one bite is that it's being extended to an int (Since it's signed, the 1 extends to a negative int).
Just take the last 8 characters of the string and it will work fine.
Ive recently had to do something like this.
I managed to achieve it through (a lot of use of the whiteboard but..) shifting the original bits right by the position of the LSB I wanted to replace and making all bits inclusive of the MSB I wanted to replace, 1's.
I then AND'ed the bits I want in place of the bits I want to replace, shifted left the same number I shifted right, OR'ing the result with the original and AND'ed by an XOR'ed mask of the replacement. (Take a breath, I'll try to explain)
Let's say I have the bytes:
1111 1010 0001 1001
and I want to replace the nibble 1010 with 0001 to produce:
1111 0001 0001 1001.
The operation I went through to achieve this is:
1) Shift right by 8 to produce:
0000 0000 1111 1010
2) OR a mask of 0xf (1111) to produce:
0000 0000 1111 1111
3) AND the replacement of 0001 with 0000 0000 1111 1111 to produce:
0000 0000 0000 0001
4) Shift left by 8 to produce:
0000 0001 0000 0000
5) Shift the mask by the LSB position and XOR with full bytes
1111 1111 1111 1111
0000 1111 0000 0000
==================
1111 0000 1111 1111
6) AND the XOR'ed, shifted mask with the original to produce:
1111 0000 0001 1001
1111 0000 1111 1111
==================
1111 0000 0001 1001
7) OR that result of the above with the replacement:
1111 0000 0001 1001
0000 0001 0000 0000
==================
1111 0001 0001 1001 << end result
==================
In java, this results in the function:
public long overwriteBits(long overwrite, long with, long shift, long mask)
{
return ((((overwrite >> shift) | mask) & with) << shift) | (overwrite & (~0 ^ (mask << shift)));
}
Where "overwrite" is the original data, "with" are the bits you want in place of the bits in position "shift" and mask is a a series of positive bits with the same length of the replacement.
To do the above I'd call (in sudo):
overwriteBits(1111101000011001, 0001, 8, 1111)
I want to mention that the above will work for replacing bits in any primitive, no need for byte arrays. e.g. Replacing 11 bits, as below:
1101001010101101 1111 0101 101 001101
with 1010 1010 101
overwriteBits(1101001010101101 1111 0101 101 001101, 1010 1010 101, 6, 11111111111)
1101001010101101 1111 0101 101 001101
1101001010101101 1010 1010 101 001101
overwriteBits(1789785421l, 1365l, 6, 0x7FF)

Categories