Set greater than 127 int byte variable in java - 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.

Related

If I assign and integer variable the integer 160 and try to store it in a byte variable, why does the value change from 160 to -96?

int einInt;
byte einByte;
einInt = 160;
einByte = (byte) einInt;
System.out.println(einByte);
// System.out.println(einByte); now outputs -96
// please try to explain this to me as detailed as possible
A byte in Java is an 8-bit signed integer, meaning it has a range of -128...127. 160 falls outside of that range, so it overflows back to the beginning of that range, and it overflows by 33 (160 - 127 = 33). Adding 1 to a byte value of 127 will overflow to -128, but since the overflow was 33, it then adds 32 to -128 which results in -96.

Why do I get 38528 when casting 10000000 to char?

Java uses 32 bits for the char tipe - so the max value is 65536.
But the following code give me the result reported in the title.
public static void main(String[] args) {
int a = 10000000;
char b = 33;
b = (char)a;
System.out.println((int)b);
}
A char is 16bit, not 32bit.
65535 is the maximum value of a char, and 10000000 is greater than that, so you cannot store that value in a char.
10000000 in binary is 100110001001011010000000
Now when casting that to char all the bits left of the 16 bits that "fit" are dropped, leaving you with 1001011010000000.
And binary 1001011010000000 in decimal is 38528.
Java uses 32 bits for the char tipe
no, Java uses 16 bit chars.
so the max value is 65536.
Almost - in terms of what is the char's max value, it's 65535, however, the max value of 2s-complement 32 bit value is 231, which is 2147483647.
But the following code give me the result reported in the title.
int a = 10000000;
char b = 33;
b = (char)a;
Well, 10000000 is sure greater than 65535, isn't it? What did you expect when trying to fit that number into a char? What you got is an overflow.

Automatic Type Promotion in 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

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

How to convert negative byte value to either short or integer?

We have a file which contains byte array in particular format like header and then followed by data. This file is generated by another java program and then we are reading that same file through another java program in the same format in which it was written.
The program which is making that file, populates lengthOfKey as byte which is right as that's what we need as shown below.
for (Map.Entry<byte[], byte[]> entry : holder.entrySet()) {
byte typeKey = 0;
// getting the key length as byte (that's what we need to do)
byte lengthOfKey = (byte) entry.getKey().length;
byte[] actualKey = entry.getKey();
}
Now as byte can only store maximum value as 127, we are seeing for some of our record lengthOfKey is coming as negative while we read the file as shown below:
Program which is reading the file:
byte keyType = dis.readByte();
// for some record this is coming as negative. For example -74
byte lengthOfKey = dis.readByte();
Now my question is : Is there any way I can find out what was the actual length of key because of that it got converted to -74 while writing it. I mean it should be greater than 127 and that's why it got converted to -74 but what was the actual value?
I think question would be how to convert negative byte value to either short or integer? I just wanted to verify to see what was the actual length of key because of that it got converted to negative value.
If the original length from entry.getKey().length is greater than 255, then the actual length information is lost. However, if the original length was between 128 and 255, then it can be retrieved.
The narrowing conversion of casting to byte keeps only the least significant 8 bits, but the 8th bit is now interpreted as -128 instead of 128.
You can perform a bit-and operation with 0xFF, which will retain all bits, but that implicitly widens the value back to an int.
int length = lengthOfKey & 0xFF;
lengthOfKey (byte = -74): 10110110
Widening it to an int, with sign extension:
lengthOfKey (int = -74): 11111111 11111111 11111111 10110110
Masking out the last 8 bits as an int:
length (int = 182): 00000000 00000000 00000000 10110110
That will convert a negative byte back to a number between 128 and 255.
If you use Guava, it provides a number of unsigned math utilities, including UnsignedBytes.
UnsignedBytes.toInt(lengthOfKey);
Notice their implementation of toInt() is exactly what #rgettman suggests.
To convert an assumed unsigned byte to an int.
int value = (byteValue >= (byte) 0) ? (int) byteValue : 256 + (int) byteValue;

Categories