Automatic Type Promotion in Java - java

I understand that the operands are automatically converted to int and we need to cast the expression to byte again. And for byte conversion the 24 bits are truncated and only 8 bits are evaluated. But I am not able to understand this output -56. The final value of e is 200 and converting it in binary gives 11001000. How is the output -56?
public class ByteIntAutomaticPromotionInExpressions {
public static void main(String[] args) {
byte e = 50;
e = (byte)(e *2);
System.out.println(e);
e *= 2;
System.out.println(e);
}
}
OUTPUT:
100
-56

As you can see here:
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
If the data type was unsigned, 11001000 would be 200 in decimal.
But since it is signed, you treat it like a negative binary number which is -(inverted bits +1) => - (0110111 + 1) = -(0111000) = -56
https://www.allaboutcircuits.com/textbook/digital/chpt-2/negative-binary-numbers/

8 bits, 2^8=256 in this case 200-256 = -56

Related

Confused with byte convertion to int

How a byte value b when uses as int in the Integer.toBinaryString() have a binary value much more than byte type can contain? I thought s1 should be in range [0, 11111111]. And how this bitwise operator (b & 0B11111111) changes the situation? It seems that it changes nothing because 0 & 1 = 0 and 1 & 1 = 1
public class Test
{
public static void main(String[] args)
{
byte b = (byte) -115;
String s1 = Integer.toBinaryString(b);
String s2 = Integer.toBinaryString(b & 0B11111111);
System.out.println(s1); // 11111111111111111111111110001101
System.out.println(s2); // 10001101
}
}
Integer.toBinaryString accepts an int, so you are actually converting the int -115 to a binary string. As far as Integer.toBinaryString is concerned, the number you passed to it is always an int. The fact that you are able to pass a byte is because there is a conversion from byte to int in an invocation context. The byte is converted to int first, then passed to Integer.toBinaryString.
What's -115 represented in 32 bit two's complement (representation of an int)? Well,
1111 1111 1111 1111 1111 1111 1000 1101
That is the binary string you got.
The & 0B11111111 here actually does something. The & operator causes the byte to undergo numeric promotion, converting it to an int. Now we have -115 as a 32-bit int, with all those extra leading 1s that we don't want. The bit mask then gets applied, resulting in the int 141 (1000 1101). We then convert this int to a binary string.
For a byte, -115 dec is 10001101 bin. If you promote that byte to an int with the same value (which is what happens when you call Integer.toBinaryString(b)), -115 dec is 11111111111111111111111110001101 bin.
Whereas if you take your int -115 and & it with 0B11111111, you get the last eight bits of 11111111111111111111111110001101, which is 10001101 bin, 141 dec.
For a byte 10001101 bin is -115, because the largest bit is negative.
For an int 10001101 bin is 141 dec, and the largest bit isn't set because you're only using the smallest 8 bits of a 32 bit integer.

Casting of byte data type

Please explain how below code is working, as we know byte data type in java allows a range from -128 to 127.
My code snippet is:
public class DataTypes {
public static void main(String args[]){
byte b = (byte)140;
System.out.println(b);
}
}
Output: -116
A Byte will have 8 bits in its memory space. Using this space it can hold 256 values. This will span from -128 to 127 including 0. To support this spanning, a Byte value will be represented in binary format using two's compliment method. The MSB (Most Significant Bit) will determine the sign (0 - positive & 1 - negative) of the value.
If we consider the case of 140, it will be clear if we represent 140 in binary format which is 1000 1100. Remember the MSB will determine the sign and a 1 means the number is a negative value and 0 means it's a positive value. In this case we have a 1 making it a negative number.
If we apply reverse process to this two's compliment, we will first get 0111 0011 by inverting all the 1s to 0s and 0s to 1s. Then by adding 1, we get 0111 0100 which is equal to 116 in decimal format. But the MSB said it's a negative value, hence -116
Maybe this will help explain. The uppermost bit determines the 'sign'(positive or negative) of a variable. Since Java does not have an explicit 'unsigned' integer form the best you can do is apply a 'bitwise' operation to the item in advance of displaying it force it to be considered 'unsigned'...or you can display it using it's hex format which is inherently unsigned.
public class DataTypes {
public static void main(String args[]){
byte b = (byte)140;
System.out.println("hex value = "+String.format("0x%02X",b)+"\n");
System.out.println("dec value = "+String.format("%d",(b & 0xff))+"\n");
}
}
and a result of
hex value = 0x8C
dec value = 140
140 is a int. It is converted to a byte, according to the Java Language Specification, section 5.1.3, as follows:
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits
The lowest 8 bits of the int with value 140 are 10001100, which is the correct value for the byte, but which is negative since its highest bit, the sign bit, is 1.
I think, when you cast the integer (140) to byte, the integer value converted into unsigned byte then b variable value is converted into signed byte. The number 140 considered as unsigned value because the number has not sign value indicator (+ or -)
Note about unsigned byte (the right value is representation (in file byte(s)) of left value):
0-127 = 0-127
(-128) - (-1) = 128 - 255

Java not printing negative binaries right

So, i'm fairly new to java, and i'm a bit confused about the byte system. So I made this program that converts integers to their base two value.
class Bits
{
public static void main(String[] args)
{
byte a;
a = 5;
System.out.println(Integer.toBinaryString(a)); /* prints 101 */
a = -1;
System.out.println(Integer.toBinaryString(a)); /* prints
11111111111111111111111111111111*/
}
}
It works as expected with positive numbers, but when I enter negative numbers, it gets weird. Now I know what two's compliment is, and it doesn't say that -1 is 11111111111111111111111111111111. It is supposed to be 11111111, right? When I change a to an int 255, which would be -1 as a byte, I get the normal result, 11111111, when I switch it to binary. Can someone explain to me why this is happening, or did I do something wrong. (I am using java 8 and i'm on a mac)
Integer.toBinaryString accepts an int as an argument. So a is casted from byte to int before being passed to the method. And yes the two's complement of -1 of a 32 bits integer is 11111111111111111111111111111111.
You should try with Integer.toBinaryString(a & 0xFF). So that a is widened to 32 bits, but then 24 most relevant bits are discarded through masking. The bit sign is kept since you were starting from a byte so the result will be correct.
You can verify it by converting the truncating the int converted from a and the parse it as an int and converting it back to a byte:
int counter = 0;
for (byte a = -128; counter <= 256; ++a, ++counter)
{
byte b = (byte)(Integer.valueOf(Integer.toBinaryString(a & 0xFF), 2) & 0xFF);
System.out.println(a+" == "+b);
}

Long to Byte Conversion

I have written the following program in Java to convert long to byte.
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a & 0xff);
System.out.println("the value of b is" +b);
}
}
The problem is I get the result -34 for the variable b.
Please tell me how to get the correct value. I want the value in bytes only.
Java's types are signed, bytes allow numbers between −128 and +127.this is the reason you were getting −34 for 222 value
long a=121;
byte b=(byte)(a );
System.out.println("the value of b is" +b);
All integer types (including byte) are signed in Java, so if you stick 222 into a Java byte you get an overflow (resulting in the negative number you saw). If you need the range 0–255 for a integral number in Java you'll need at least a short.
However, if you're just going to write that result somewhere as a single byte you don't need to worry, as its bit pattern representation is exactly the same as 222 in an unsigned byte.
You can use the java.lang.Long class' byteValue() method:
byte b = a.byteValue();
You will have to make a Long type object as such:
Long a = new Long(222);
And as others have noted, this will return -34 due to overflow of the range that can be represented by a byte which is 8 bits.
When you print a byte it assumes a range of -128 to 127.
If you print
byte b = (byte) 222;
you should expect to get a negative number.
If you want to store the range 0 to 255 you need to convert it when you get the value out.
int i = 222;
byte[] b = { (byte) i };
int i2 = b[0] & 0xFF; // give me the original unsigned 0 to 255.
assert i == i2;
You can invent all sorts of encoding. e.g. Say you want to store numbers which are only in millions say 0 to 200 million or decimal numbers -1.00 to 1.00 in a byte. You might first think this is impossible because a byte only stores 8 bits.
// store millions.
byte b = (byte) (i / 1000000);
int i = (b & 0xff) * 1000000;
// store decimal from -1.00 to 1.00
byte b = (byte) Math.round(d * 100);
double d = b / 100.0;
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a);
System.out.println("the value of b is" +b);
}
}
This byte bValue = (byte) num; statement is converted into a byte format.

Set greater than 127 int byte variable in java

I write the following sample code:
public static void main(String[] args) throws Exception
{
byte number_1 = 127;
byte number_2 = (byte) 128;
System.out.println("number_1 = " + number_1);
System.out.println("number_2 = " + number_2);
}
I get the following result in output:
number_1 = 127
number_2 = -128
I know range of a byte data type( -128 to 127).
Is my sample is correct? What happened? Is there a two's complement operation? I don't understand this behavior.
Because one byte can hold upto -128 to 127 only, This is expected behavior of overflow
Check with this loop
for(int index = 0 ; index < 258 ; index ++ ){
System.out.println((byte)index);
}
Also See
Endless for loop
Nice comic illustration
This is because of byte range . A byte can store values from -128 to 127 only.
You're seeing the effect of a narrowing primitive conversion: casting the integer literal 128 to a byte results all all but the last byte being thrown out. The last byte of an integer has value 10000000, which when interpreted in two's complement as a one-byte value comes out to -128.
In contrast, the same value interpreted as a four-byte value filled with zeroes on the left, i.e. 00000000 00000000 00000000 10000000, equals 128.
From the official documentation on primitive datatypes :
byte: The byte data type is an 8-bit signed two's complement integer.
It has a minimum value of -128 and a maximum value of 127 (inclusive).
To respond your question : How to Set greater than 127 int byte variable in java ?
The best way to represent an unsigned byte is to use a signed integer, because the Java VM represents bytes as 32 bits, you're not saving anything by using a byte.
Because one byte can hold upto -128 to 127 only, when you transform a int which is
more than 127 or less than -127, the java compiler makes the change automatically.
In fact, the following statement
byte number_2 = (byte) 128;
has been changed to
byte number_2 = (byte) -128;
Once you check out the bytecode using javap, you will find it.

Categories