Type casting into byte in Java - java

I am a beginner in Java. I came across a concept called Type Casting.
I have the following snippet-
class Demo
{
byte b;
int a=257;
double d= 323.142
b=(byte)a;
System.out.println(b);
b=(byte)d;
System.out.println(b);
}
The output for the code is 1
67
Can anybody explain me the outputs.
Thanks in Advance!

The byte type is encoded on 8 bits, so it takes its values between -128 and 127. In your case, casting by byte is the same as computing a modulo and rounding to an int. Try the following code, the output is the same:
int a = 257;
double d = 323.142;
System.out.println(a % 128);
System.out.println((int) d % 128);

In both cases you are doing a narrowing conversion, which may result in loss of information.
Conversion of int to byte
you convert an int whose value is 257 (00000000 00000000 00000001 00000001 in binary) to a byte. Therefore, only the lowest (right) byte of the int is kept. Therefore the result is 00000001 in binary, which is 1.
Conversion of double to byte
This conversion is more complicated.
In the first step 323.142 is converted from double to int, so it becomes 323.
The second step is the same as the first conversion :
323 is 00000000 00000000 00000001 01000011 in binary.
Converting 323 to byte keeps the lowest (right) byte, which gives you 67.
Here's what the JLS says about this conversion :
A narrowing conversion of a floating-point number to an integral type
T takes two steps:
In the first step, the floating-point number is converted either to a long, if T is long, or to an int, if T is byte, short, char, or
int, as follows:
If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0.
Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding
toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there
are two cases:
a. If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.
b. Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.
Otherwise, one of the following two cases must be true:
a. The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is
the smallest representable value of type int or long.
b. The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is
the largest representable value of type int or long.
In the second step:
If T is int or long, the result of the conversion is the result of the first step.
If T is byte, char, or short, the result of the conversion is the result of a narrowing conversion to type T (§5.1.3) of the result
of the first step.

byte b;
int a=257;
double d= 323.142
b=(byte)a; // 257-256=1
System.out.println(b); // now b is 1
b=(byte)d; // 323.142-256=67
System.out.println(b); // now b is 67
byte data type is an 8-bit signed two's complement integer(This is important in second case, why 67.142 become 67). byte in Java is signed, so it has a range -2^7 to 2^7-1 - that is, -128 to 127. Since 257 is above 127, you end up wrapping around to 257-256=1. That is 256 is added or subtracted until it falls into range.Same scenario happen in the second case too.

Byte can store between the range of -128 to 127 which means 1 Byte (8 bit).
Binary value of 257 is 100000001 after converting to byte which means 8 bit (from LSB to MSB) which will get value of 00000001 which is nothing but 1. Here you are explicitly converting the type so data loss will take place while converting higher data type to lower data type. Similarly for the later one. Hope this will help you.

Hexadecimal representation of
(257) = 0x101
(323) = 0x143
byte stores only one byte of data and as you see the highlighted part in above hex representation:-
b = 0x01 = 1 for 257 and b = 0x43 = 67 for integer part of 323.14
Note:- In Java a double uses a 52 bit mantissa, hence we can represent a 32 bit integer without lost of data.

Because 257 = 100000001b
but when you cast it in byte you get only 8 bit of this number:
00000001b = 1

Related

How to calculate the value of any primitive , who has out of range value

Example
byte x;
x=(byte)2355;
System.out.println(x);
so, how can I calculate the value which will be in x;
The 2355 literal value is interpreted as an int, which in Java is represented by the following 32 bits:
00000000000000000000100100110011
A byte has only 8 bits, so you lose the leading 24 bits:
00110011
Converted back to decimal, this leaves you with a value of 51.
You can find the bit sizes of the various primitive data types here. Also keep in mind that you need to take two's complement into account when dealing with signed primitives.
The range of the byte data type is -128 to 127 (inclusive). So if you want to deal with numbers outside that range then you can try casting the data type to short, int or long.

How does overflow work in java?

I've read about overflow, I know that "Overflow is when a number is so large that it will no longer fit within the data type, so the system “wraps around” to the next lowest value and counts up from there".
For example:
short s = (short)1921222; // Stored as 20678
In that example we started counting from -32768 (Short.MIN_VALUE), but when I try to prove in another integer data types, it doesn't seem work the same way...
byte b = (byte)400; // Stored as -112
The example above started counting from 0 that was the only way I found to get -112
I don't know if I am doing something wrong.
The Java Language Specification says:
The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units.
So, short and byte are both two's complement integers.
short is 16 bits, meaning it can hold 2^16 = 65536 different values. After the 65536th value, it overflows.
1921222 modulo 65536 is 20678 . This is less than 32768 (2^15, the turning point for the two's complement) so we keep a positive number.
byte is 8 bits, meaning it can hold 2^8 = 256 different values. This one overflows after the 256hth value.
400 modulo 256 is 144. This value is higher than 128, the turning point for the two's complement - hence it will be interpreted as a negative two's complement number.
The cast is truncating the number. (JLS)
0000 0001 1001 0000
loses the high byte to become
1001 0000
which is -112.
In java, byte primitive type is an 8 bit signed integer, that's why you got -112 from calling:
byte b = (byte) 400;
You can avoid that and get its un-signed value, by binary adding it with 0xFF like this:
int b = (byte) 400 & 0xFF;
For further details you can check:
Java Primitive data types Documentation.
How to Convert Int to Unsigned Byte and Back
In addition to the other answers, you can get to that answer by manual calculation as well.
In Java, the data type byte is an 8-bit, signed integer. So the values are in the interval [-128, 127]. If you have a value of 400 and you want to see the actual value for that type, you can subtract the size of the interval from that number until you reach a value that's inside the interval.
As I said, byte is 8 bit, so the size of the interval is 256. Subtract that from your initial value: 400 - 256 = 144. This value is still outside of the interval so you have to subtract again: 144 - 256 = -112. This value is now inside the interval and is indeed the value you've seen in your test.
The same is true for your first example: short is 16 bit and signed, so the interval is [-32768, 32767] with size 65536. Doing repeated subtraction from the value 1921222 will eventually give you the value 20678 as seen in your test.

Casting of primitives type

I am beginner in Java. I cannot understand this line even after a long try.
byte num=(byte)135;
this line gives result -121 why it is in signed number ?
Can any one elaborate it ?
In Java, bytes are always signed, and they are in the range -128 to 127. When the int literal 135 is downcasted to a byte, the result is a negative number because the 8th bit is set.
1000 0111
Specifically, the JLS, Section 5.1.3, states:
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.
When you cast an int literal such as 135 to a byte, that is a narrowing primitive conversion.

buff.getInt() & 0xffffffffL is an identity?

Here is some code I have been looking at:
public static long getUnsignedInt(ByteBuffer buff) {
return (long) (buff.getInt() & 0xffffffffL);
}
Is there any reason to do buff.getInt() & 0xffffffffL (0xffffffffL has 32 bits of 1's in the 32 least significant bits)? It looks to me like the result will always be buff.getInt().
In short, it's because the method needs to convert a signed int (which all Java ints are) to an unsigned quantity.
If you were to just do (long) buff.getInt(), and buff.getInt() returned -1, you'd end up with -1. And that's a signed quantity -- not what the method is supposed to return.
So what the method does is forces buff.getInt() to become unsigned by ANDing the int bits with 0x00000000FFFFFFFF. This effectively "reinterprets" the bits of the signed int as an unsigned int (really a signed long, but as only the lower 32 bits are ever going to be set, it works as an unsigned int), producing the desired result.
For example, (working with bytes for brevity).
Say buff.getInt() is really buff.getByte(), and returns -1 == 0xFF
Try to cast that to an int, you'll end up with 0xFFFFFFFF -- still -1, due to the magic of sign extension.
However, mask that with 0xFF, and you'll end up with 0x000000FF == 255 -- the desired value.
I believe the explicit cast is unnecessary (it isn't on my machine), but I could be missing something...
Edit: Turns out the cast actually is unnecessary. From JLS section 5.6.2:
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
If either operand is of type double, the other is converted to double.
Otherwise,if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
If buff.getInt() is a negative number, it will still be a negative number when casting it to a long. But it'll be sign extended.
So, if you want to preserve the bit pattern, e.g. to try to interpret the values as unsigned values, &0xffffffffL will mask off those bits.
e.g. if buff.getInt() returns -2147483648, the returned int will have a bit pattern of 0x80000000. Cast to long, that'll still be -2147483648 , but with a bit pattern of 0xffffffff80000000. 0xffffffff80000000 & 0xFFFFFFFF preserves the original bit pattern of 0x80000000
Integers in Java (int and long) are signed, two's complement numbers. That means the high digit is 0 if the number is positive (or 0), and -1 if it's negative.
To convert from an int to a long, Java uses sign extension. This means that the numbers it "fills in" to the left depend on that leftmost digit. To illustrate with going from 4-bit to 8-bit numbers:
1 = 0001 -> 0000 0001
-1 = 1111 -> 1111 1111
So if you want to interpret 1111 as a signed number (ie, 15), you can't just convert it from 4 bits to 8: you'd get 1111 1111, which is -1. What you want is 0000 1111, which is 15.
To do this, you need to do a bitwise AND on the number to mask out the high bits which have been filled in, and turn those into 0's.

How does double to int cast work in Java

I am new to Java, and wondering how does double to int cast work ? I understand that it's simple for long to int by taking the low 32 bits, but what about double (64 bits) to int (32 bits) ? those 64 bits from double in binary is in Double-precision floating-point format (Mantissa), so how does it convert to int internally ?
It's all documented in section 5.1.3 of the JLS.
In the first step, the floating-point number is converted either to a long, if T is long, or to an int, if T is byte, short, char, or int, as follows:
If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0.
Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:
If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.
Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.
Otherwise, one of the following two cases must be true:
The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is the smallest representable value of type int or long.
The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or long.
(The second step here is irrelevant, when T is int.)
In most cases I'd expect this to be implemented using hardware support - converting floating point numbers to integers is something which is usually handled by CPUs.
Java truncates its value if you use (int) cast, as you may notice:
double d = 2.4d;
int i = (int) d;
System.out.println(i);
d = 2.6;
i = (int) d;
System.out.println(i);
Output:
2
2
Unless you use Math.round, Math.ceil, Math.floor...
You may want to read the Java specification:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3
The relevant section is 5.1.3 - "Narrowing Primitive Conversion".

Categories