This question already has answers here:
Multiplying two bytes
(2 answers)
Closed 4 years ago.
I have a problem with the below Java statements:
byte b = 10;
byte r = (byte) (b * b); // Giving correct result
byte r = (byte) b * b; // Giving error " POSSIBLE LOSS OF PRECISION"
Why is it mandatory to give parentheses to b * b?
(byte) b * b casts the value of the first b to byte (which is redundant since it was already byte), and multiples it by the value of the second b. Multiplying two bytes promotes them to int first, since there is no * operator for bytes. Therefore the result is int, and cannot be assigned to a byte variable.
On the other hand, (byte)(b * b) casts the int multiplication result to byte, which can be assigned to a byte variable.
This is covered in the JLS in 5.6.2. Binary Numeric Promotion:
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
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.
Casting problem
byte r = (byte) (b * b);
It casts the (byte) type to the result of (b * b)
byte r = (byte) b * b;
It casts the (byte) type to the first b only, therefore it will become ((byte) b) * b
By the precedence rule you are casting only the first b to byte instead of the whole result.
And Java follow some rules, as you can see here
All integer values (byte, short and int) in an arithmetic operations (+, −, *, /, %) are converted to int type before the arithmetic operation in performed. However, if one of the values in an arithmetic operation (+, −, *, /, %) is long, then all values are converted to long type before the arithmetic operation in performed.
So, by just casting the first b you are doing this:
byte = byte * integer
Hence:
byte = integer
Thus, raised error.
Variables of type byte must be [-128,127], that is why the compiler must not accept any operation, b*b;b+b;b-b;b/b without a cast on the result of operation, like: (byte)(b*b).
In the code below, when you change the result type to int it compiles.
byte b=10;
byte c=(byte)b*b; //incompatible but correct when c is int
byte d=((byte)b)*b; //incompatible but correct when d is int
byte r=(byte)(b*b);
byte t= b*b; //incompatible but correct when t is int
byte e=(byte)b/b; //incompatible but correct when e is int
byte f=((byte)b)/b; //incompatible but correct when f is int
byte o=(byte)(b/b);
byte w=b/b; //incompatible but correct when w is int
byte g=(byte)b+b; //incompatible but correct when g is int
byte p=((byte)b)+b; //incompatible but correct when p is int
byte q=(byte)(b+b);
byte x=b+b; //incompatible but correct when x is int
byte h=(byte)b-b; //incompatible but correct when h is int
byte v=((byte)b)-b; //incompatible but correct when v is int
byte s=(byte)(b-b);
byte y=b-b; //incompatible but correct when y is int
byte k=(byte)b;
byte u=b;
NOTE
As #andy Truner pointed out in comments, when b is final, all the previous instructions compile!!, except for the following set up:
final byte fn=-120;
byte z=fn-b; //this does not compile even when both final, because the result would be -130, out of the byte type interval!!
Related
The rules for promotion is "when operands are of different types, automatic binary numeric promotion occurs with the smaller operand type being converted to the larger". But the operands are of same type for example,
byte=byte+byte // Compile time error... found int..
So why is it so?
There's no + operator for byte. Instead, both operands are promoted to int, so you've got
byte = byte + byte
... becomes (widening to find + operator) ...
byte = int + int
... becomes (result of + operator) ...
byte = int
... which then fails because there's no implicit conversion from int to byte. You need to cast:
byte a = 1;
byte b = 2;
byte c = (byte) (a + b);
Here are the actual rules for numeric promotion, from section 5.6.2 of the JLS:
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order, using widening conversion (§5.1.2) to convert operands as necessary:
If any of the operands is of a reference type, unboxing conversion (§5.1.8) is performed. Then:
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.
You were provided with correct answer about automatic promotion to 'int'.
There is one more note about that - compound assignment operators behave as they have an implicit type case. Example:
byte b1 = 1;
byte b2 = 2;
b1 = b1 + b2; // compilation fails
b1 += b2; // compilation successful
I would like to talk about Promotion in general
Java can evaluate only arithmetic expressions in which the operands’ types are identical
For example, in an expression containing int and double values, the int values are promoted to double values for use in the expression.
in another word
double someVar = 1 / 2;// someVar = 0
but
double someVar = (double)1 / 2;// someVar = 0.5
why?
we use the (double) cast operator to create a temporary
floating-point copy of its operand "1" (it's called explicit conversion)
The calculation now consists of a floating-point value (the temporary double copy of 1) divided by the integer 2
according to the above statement, Java performs an operation called promotion (or implicit conversion), so the int values are promoted to double values for use in the expression => the integer 2 is promoted to double
the expression became double someVar = 1.0 / 2.0; // someVar= 0.5
hope this is helpful, even if it is out of the core of the question
To understand this you should refer the 2 things:
Implicit Casting:
byte (8 bit) -> short (16 bit) -> int (32 bit) -> float (32 bit) -> double (64 bit)
char (16 bit) -> int (32 bit)
Arithmetic Operator Rules
Operator Precedence Rule : This rule states that Group of (*,/, %) will be evaluated first. Then Group of (+,-) operator will be evaluated. From a same Group of Operators, calculate from the left.
Operand Promotion Rule : This rule states that Operands having data type smaller than int will be promoted to int. order of promotion (byte->short->int, char->int)
Same Type Operand Rule: This rule states that if both operands are int,long,float,double then the same type is carried to the result type.
i.e. long+long => long , float + float => float, int+int => int
Mix Type Operand Rule : Follow the order of Promotion (int->long->float->double) if any of the operand is from the above order then the smaller will be promoted to the bigger one and result will be calculated in bigger type.
i.e. long + double => double , int + long => long
From this SO question, and above answers due to + arithmetic operator, both operands are converted to type int.
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2; // compile time error
In above code, value of b1 and b2 will be resolved at runtime, so compiler will convert both to int before resolving the value.
But if we consider the following code,
final byte b1 = 1;
final byte b2 = 2;
int b3 = b1 + b2; // constant expression, value resolved at compile time
b1 and b2 are final variables and values will be resolved at compile time so compilation won't fail.
Bytes in Java range from -128 to 127. If over 127 they overflow. So I assigned 128 to a byte variable to know how overflow work, but the compiler shows a error message: "Type mismatch: cannot convert from int to byte".
Why do I get a compiler error instead of it overflowing?
javac will let you assign values within range to bytes. When you go out of range, the value needs to be explicitly cast.
byte b = (byte)128;
Would work with the compiler. To see overflow you might try
byte b = 127;
b += 1;
System.out.println(b);
-128
The nuts and bolts can be found in the JLS. Java will do arithmetic as int, or long.
byte a = 1;
byte b = 2;
//byte c = a + b; //fails because the operation is performed as an int.
byte c = (byte)(a + b);
A byte is an 8-bit signed integer value that can hold values between -128 and 127.
You can cast 128 into a byte 'byte b = (byte)128;', but then b will just equal -128 because of how twos-complement numbers work.
Integer constants like 1, -32, 128, or 7654321 have int type in Java. Assigning an int value to a byte variable is simply not allowed. This is why you get the error cannot convert from int to byte. To get around it, you have to convert the int value to byte with a type cast, b=(byte)128.
The real question should be, why do you not get an error for this code?
byte b = 100; // !!!! ASSIGNING int TO byte !!!!
You don't get an error here because of this a special "assignment conversion" rule that only applies for compile time constant expressions:
A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
Type
byte B = (byte)128;
instead of byte B = 128;
Here are codes,the last second row couldn't compile out cause of the result is int?So,can I
solve that every non integer type in java process as integer in arithmetic?
And I am learning English from all guys,thank you.
byte a=0;
for(int i=0;i<128;i++){
a=(byte)i;
}
byte b=1;
byte c=0;
c=b+a;
System.out.println(b);
Addition operation in java between two shorts or bytes happens after converting both the operands to int and results in an int. So you need to cast your result to byte as it is a lossy conversion. See this
You have to cast a or the result of the addition of a and b to a byte, since a is an integer and it's value might not fit into a byte.
Example:
c = (byte) ((byte) a + b);
or
c = (byte) (a + b);
This way, b gets implicitly converted to an integer, the result is then casted to a byte again.
public class Multicast {
public static void main(String[] args) {
System.out.println((int) (char) (byte) -2);
}
}
I am confuse about the type conversion and also giving unexpected result (it prints 65534, not -2 as expected).
The confusing result is due to the fact that char is an unsigned type. When -2 is converted to char, its bit representation becomes 1111111111111110 in binary, because two's complement representation is used. That representation becomes a positive 65534 when converted to decimal - the result you see printed by your program.
In Java, char is an unsigned type (and byte is a signed type). So (char)-2 is 65534. Then you widen that to be an int.
your confusion on the results of your code is partly due to sign-extension. I'll try to add a more detailed explanation that may help with your confusion.
char a = '\uffff';
byte b = (byte)a; // b = 0xFF
this DOES result in the loss of information. This is considered a narrowing conversion. Converting a char to a byte "simply discards all but the n lowest order bits".
The result is: 0xFFFF -> 0xFF
char c = (char)b; // c = 0xFFFF
Converting a byte to a char is considered a special conversion. It actually performs TWO conversions. First, the byte is SIGN-extended (the new high order bits are copied from the old sign bit) to an int (a normal widening conversion). Second, the int is converted to a char with a narrowing conversion.
The result is: 0xFF -> 0xFFFFFFFF -> 0xFFFF
int d = (int)c; // d = 0x0000FFFF
Converting a char to an int is considered a widening conversion. When a char type is widened to an integral type, it is ZERO-extended (the new high order bits are set to 0).
The result is: 0xFFFF -> 0x0000FFFF. When printed, this will give you 65535.
I recently noticed an idiosyncrasy of Java regarding basic arithmetic operations in Java. With the following code
byte a = 3;
byte b = 4;
byte c = a * b;
I get a "type mismatch" compilation error...
Are basic arithmetic operations in Java (+, -, *, /) only performed on primitive data types of int and higher order (long, double, etc.), whereas arithmetic operations on byte and short are first cast to int and then evaluated?
Operations on byte, char and short are widened to int unless the compiler can determine the value is in range.
final byte a = 3, b = 4;
byte c = a * b; // compiles
final byte a = 3, b = 40;
byte c = a * b; // compiles
final int a = 3, b = 4;
byte c = a * b; // compiles !!
but
byte a = 3, b = 4;
byte c = a * b; // doesn't compile as the result of this will be `int` at runtime.
final byte a = 30, b = 40;
byte c = a * b; // doesn't compile as the value is too large, will be an `int`
BTW This compiles even though it results in an overflow. :]
final int a = 300000, b = 400000;
int c = a * b; // compiles but overflows, is not made a `long`
The result of integer operations is either int or long. This is spelled out in the JLS:
4.2.2. Integer Operations
The numerical operators, which result in a value of type int or long:
The unary plus and minus operators + and - (§15.15.3, §15.15.4)
The multiplicative operators *, /, and % (§15.17)
The additive operators + and - (§15.18)
...
Also:
5.6.2. Binary Numeric Promotion
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
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.
...
Binary numeric promotion is performed on the operands of certain operators:
The multiplicative operators *, / and % (§15.17)
The addition and subtraction operators for numeric types + and - (§15.18.2)
The numerical comparison operators <, <=, >, and >= (§15.20.1)
The numerical equality operators == and != (§15.21.1)
The integer bitwise operators &, ^, and | (§15.22.1)
In certain cases, the conditional operator ? : (§15.25)