Why does this java code
long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);
when run, output
1
1
107374182400
0
instead of the expected
1
1
107374182400
107374182400
output?
long a2 = 100L * 1024 * 1024 * 1024;
In this operation however at least one operand is long. hence the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. The other non-long operand are
widened to type long by numeric promotion and resulted value gets stored to to variable a2.
long a1 = 100 * 1024 * 1024 * 1024;
The constant expression of plain integer, the result of the expression was computed as a type int. The computed value however too large to fit in an integer and hence overflowed, resulting in 0 and gets stored to a1 variable.
Edit: As is asked in the following comment:
Why doesn't it go negative?
Because while in integer computation the second computation is equivalent to 25 * 2^32 where ^ has the power meaning and 2^32 integer value is 0. However, to explain why it's value is 0: In binary:
100 * 1024 * 1024 * 1024 == 25 * 2^32;
Integer.MAX_VALUE = 2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000
2 ^ 31 is a negative integer(-2147483648) as the sign bit is 1 And hence 2 ^ 32 is just a multiplication of 2 to 2 ^ 31: a left shift and the sign bit will become 0 and hence the result is 0.
Check out the java language specification: 4.2.2: Integer operation for details.
107374182400 is exactly 25 times the full range of an integer (2^32), which means that if you try to fit it into an integer it will overflow. And because it would fit exactly 25 times it ends up precisely on 0 (this is a coincidence and other huge multiplications may end up either positive or negative). And you are using an integer right up to the point you cast to long
long a1 = 100 * 1024 * 1024 * 1024;
is equivalent to
int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;
If you put a single long in the expression, it is forced to use long maths not integer maths which removes the problem
It might be that the expression on the right of a1 is first calculated as an int and later on converted to long. If it equals 0 as an int it'll stay 0 as a long
As per the documentation of Lexical Literals it is mentioned that,
The type of a literal is determined as follows:
- The type of an integer literal (§3.10.1) that ends with L or l is long (§4.2.1).
- The type of any other integer literal is int (§4.2.1).
Thus your expression, 100 * 1024 * 1024 * 1024 is evaluated as int primitive data type because l or L is not mentioned in any numeric value. and the result is 107374182400 i.e. in Binary it is 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 and int is 32-bit so low 32-bit are taken as mentioned in Example 4.2.2-1. Integer Operations which results to 0
It is also mentioned in same documentation that,
If an integer operator other than a shift operator has at least one operand of type long, then
the operation is carried out using 64-bit precision, and the result of the numerical operator is of
type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion
It means any value in expression contains l or L then all the int values will be expanded to 64 bit.
EDIT In the comment it is also asked
Why doesn't it go negative?
I think it also answers the above question
long a4 = 1L; //No problem in this
long a3 = 1; //here left side primitive is considered as integer and at the time of assignment it will be casted to long so again result is as expected
long a2 = 100L * 1024 * 1024 * 1024; (here you have used 100L so others will be type casted to Long so expected output)
long a1 = 100 * 1024 * 1024 * 1024; (as by default any primitive digit is considered as int in java, it will consider this as integer multiplication so it goes out of range and results in 0)
Here's what you did :
You assigned 100 * 1024 * 1024 * 1024
to a long data type but you didn' said that 100 * 1024 * 1024 * 1024 is a long value
By default java compiler thinks that its an integer. Since integer cannot hold that much value, it will show wrong result. Hope it helps !
reason is integer overflow
as output of 100 * 1024 * 1024 * 1024; is an integer(int) not long
and in long a2 = 100L * 1024 * 1024 * 1024; you are specifying that one of the value is long (here 100L) and multiplication with that value results in long value which gets correctly stored in a2
In Java, if you have int * int, it will compute the output as an int. It only gives the result as a long if you do int * long.
In your case, the 100 * 1024 * 1024 * 1024 has a result that overflows int.
So, adding a "L" makes the operand to be a long, and the computation stores the values in long. And of course, no overflow occurs and a correct result can be outputed (i.e. a2).
Number 3 worked because you specified a long type which is 100L. Thats why it is a long multiplication and could be stored. On the other hand number 4 is an integer multiplication with max value 2^32-1 thats why you got an overflow and the zero default valued appeared.
Related
I was reading Unsigned arithmetic in Java which nicely explained how to do unsigned longs using the following method
public static boolean isLessThanUnsigned(long n1, long n2) {
return (n1 < n2) ^ ((n1 < 0) != (n2 < 0));
}
However I'm confused by Guava's implementation. I'm hoping someone can shed some light on it.
/**
* A (self-inverse) bijection which converts the ordering on unsigned longs to the ordering on
* longs, that is, {#code a <= b} as unsigned longs if and only if {#code flip(a) <= flip(b)} as
* signed longs.
*/
private static long flip(long a) {
return a ^ Long.MIN_VALUE;
}
/**
* Compares the two specified {#code long} values, treating them as unsigned values between
* {#code 0} and {#code 2^64 - 1} inclusive.
*
* #param a the first unsigned {#code long} to compare
* #param b the second unsigned {#code long} to compare
* #return a negative value if {#code a} is less than {#code b}; a positive value if {#code a} is
* greater than {#code b}; or zero if they are equal
*/
public static int compare(long a, long b) {
return Longs.compare(flip(a), flip(b));
}
Perhaps some diagrams help. I'll use 8 bit numbers to keep the constants short, it generalizes to ints and longs in the obvious way.
Absolute view:
Unsigned number line:
[ 0 .. 0x7F ][ 0x80 .. 0xFF]
Signed number line:
[ 0x80 .. 0xFF ][ 0 .. 0x7F]
Relative view:
Unsigned number line:
[ 0 .. 0x7F ][ 0x80 .. 0xFF]
Signed number line:
[ 0x80 .. 0xFF ][ 0 .. 0x7F]
So signed and unsigned numbers largely have the same relative order, except that the two ranges with the sign bit set and the sign bit not set are swapped in order. Inverting that bit of course swaps the order.
x ^ Long.MIN_VALUE inverts the sign bit for a long.
This trick is applicable for any operation that depends only on the relative order, for example comparisons and directly related operations such as min and max. It does not work for operations that depend on the absolute magnitude of the numbers, such as division.
Consider the bits that make up a long type. Performing ^ Long.MIN_VALUE converts a regular two's complement signed representation that holds [-263, 263-1] values into an unsigned representation that holds [0, 264-1] values.
You can see the process by taking the smallest long value, adding one and "flipping" while inspecting the bits (e.g. with Long.toBinaryString()):
Long.MIN_VALUE ^ Long.MIN_VALUE is 00..00 (all 64 bits unset)
(Long.MIN_VALUE + 1) ^ Long.MIN_VALUE is 00..01
(Long.MIN_VALUE + 2) ^ Long.MIN_VALUE is 00..10
(Long.MIN_VALUE + 3) ^ Long.MIN_VALUE is 00..11
and so on until:
Long.MAX_VALUE ^ Long.MIN_VALUE is 11..11 (all 64 bits set)
The "flip" is done because Longs.compare() needs input as unsigned [0, 264-1] values as per the method javadoc in your example:
/**
* Compares the two specified {#code long} values, treating them as unsigned values between
* {#code 0} and {#code 2^64 - 1} inclusive.
*
I'm trying to get a long 2 GB in bytes to test a file size. The result appears to overflow despite being assigned to a Long. This doesn't make any sense to me because in the definition of long, the maximum value is 2^(63)-1 which is much larger than 2 * 1024^3. I have a feeling that it has something to do with a JVM optimization using Integers, but then I'm not sure how to get around this. How should I cast it so it doesn't overflow?
long l = 2 * 1024 * 1024 * 1024;
System.out.println(l);
System.exit(0);
long l = 2 * 1024 * 1024 * 1024;
You are initializing an int here, not a long!
When not suffixed, numeric integral literals are ints by default.
You want to write:
// NOTE THE L SUFFIX
long l = 2L * 1024 * 1024 * 1024;
It is enough for the first literal to be a long for the result of an arithmetic operation to be a long as well.
Append the numbers with L to indicate that they are long values explicitly in the statement:
long l = 2L * 1024L * 1024L * 1024L;
Else, the values in the expression will be treated as integers and then simply assigned to a long.
People have rightly pointed out the problem. Also important here is the evaluation order. In the expression
long l = 2 * 1024 * 1024 * 1024;
2 * 1024 * 1024 * 1024 is evaluated first and then the result is assigned to l. Since the RHS expression is purely and integer, its evaluated as integer (which you saw as overflow) and then assigned to variable on the LHS.
when you change the expression to
2L * 1024 * 1024 * 1024, its correctly evaluated as Long.
This question already has answers here:
Multiplication operation in Java is resulting in negative value
(4 answers)
Closed 8 years ago.
final long COOKIE_TIMEOUT = 1000 * 60 * 60 * 24 * 30;
Output: -1702967296
Someone told me to put L after 1000 & it works
final long COOKIE_TIMEOUT = 1000L * 60 * 60 * 24 * 30;
Output: 2592000000
Why does that happen?
Integer overflow, put 1000L, this will force long conversion
UPDATE
Slightly longer explanation:
If you just do 1000*10 for example, java will see them as integers.
In your original code, you were doing an integer calculation which overflowed, then cast the overflowed value to long.
However if you put L after the first number, java will see them as longs (left-most operand defines the granularity) and you won't get an overflow.
As another example take this code:
double a = 5 / 2;
double b = 5d / 2;
System.out.println(a + " != " + b);
This will print out:
2.0 != 2.5
Why? When calculating a, java sees 5 and 2 as integers and does an integer division, then casts the result to a double. When calculating b you tell java that 5 is actually a double at which point it performs a double division.
Although COOKIE_TIMEOUT is long the right-hand expression consists of integers, so its type is int. The result is greater than Integer.MAX_VALUE that causes overflow. When at least one operand in your expression belongs to higher type (e.g. long) whole expression becomes long and overflow does not happen.
This is what you did in your second example when you added L modifier after one of the numeric constants. This constant became long, so the expression became long too.
This behavior is due to the type of the expression selected by the Java compiler. In this case it looks something like so:
int * int -> int (which overflows here during the multiplication)
long * long -> long
long * int = long * long (by promotion) -> long
int * long = long (by promotion) * long -> long
This promotion happens pretty much universally for the math operators: the widest/largest type is used, with the smaller type being promoted and the x op x -> x expression being applied (classically, integer vs. floating division).
The L results in a long value and thus the multiplication selected is long * long (by promotion) -> long, which is free from the immediate overflow discovered. The long expression result type propagates to all the other multiplications.
Bonus points: it would still fail (overflow) if written as 1000 * 60 * 60 * 24 * 30 * 1L, why?
It is greatter than Integer.MAX_VALUE which is 2147483647
By default all numeric litaral are considered as Integer. to define a Long numeric value you have to add L or 'l' with the number.
The reason of that behavior is integer overflow.
Your first statement can be understand like this:
long time = 1000 * 60 * 60 * 24 * 30;
is the same as
int time = 1000 * 60 * 60 * 24 * 30;
long timel = time;
First you compute the expression, then you assign to long type;
When you put suffix L to literal you define it as long type.
JSL 3.10.1. Integer Literals
An integer literal is of type long if it is suffixed with an ASCII
letter L or l (ell); otherwise it is of type int (§4.2.1).
long time = 1000L * ( 60 * 60 * 24 * 30);
can be written also as
long time = ((long) 1000) * ( 60 * 60 * 24 * 30);
More about Primitive Data Types
It is causing for Integer overflow(Max value upto 2147483647).
You can postfix L at the end of the any numeric value.
Like 1000L
Then it forcely converts into Long type
What happens here is that the right hand side is evaluated before the assignment to the left hand side. Since you are multiplying several ints, the resulting type will be int. Then, after evaluating the right hand side, it will see that it is supposed to assign this value to a long, and do the casting automatically.
So you have:
Evaluated right hand side as int: 1000 * 60 * 60 * 24 * 30 = 2,592,000,000.
The maximum value of an int is: 2,147,483,647.
So you have an overflow, which makes the int negative. This is then assigned to a long, still negative.
When you specify one of the operands on the right hand side to be long, then the expression will be evaluated has a long, which has a much larger maximum value.
Every number in the formula is an Integer, hence Java will perform all calculations in Integer and store the result temporarily as Integer. However the result exceeds Integer Max range (overflow), so it becomes negative.
1000 * 60 * 60 * 24 * 30 = 2592000000 (exceeds Integer.MAX_VALUE)
Only when Java needs to assign it to the Long variable Java will cast it into a Long. Since the result is already wrong result (due to overflow) then the Long variable will be assigned with the wrong result.
However if you already declare the 1000 as Long (1000L), then the remaining calculations will be done as Long instead of Integer.
Today I was learning about the left shift bit operator (<<). As I understand it the left shift bit operator moves bits to the left as specified. And also I know multiply by 2 for shifting. But I am confused, like what exactly is the meaning of "shifting bits" and why does the output differ when value is assigned with a different type?
When I call the function below, it gives output as System.out.println("b="+b); //Output: 0
And my question is: how does b become 0 and why is b typecasted?
public void leftshiftDemo()
{
byte a=64,b;
int i;
i=a << 2;
b=(byte)(a<<2);
System.out.println("i="+i); //Output: 256 i.e 64*2^2
System.out.println("b="+b); //Output: 0 how & why b is typecasted
}
Update (new doubt):
what does it mean "If you shift a 1 bit into high-order position (Bit 31 or 63), the value will become negative". eg.
public void leftshifHighOrder()
{
int i;
int num=0xFFFFFFE;
for(i=0;i<4;i++)
{
num=num<<1;
System.out.println(num);
/*
* Output:
* 536870908
* 1073741816
* 2147483632
* -32 //how this is -ve?
*/
}
}
When integers are casted to bytes in Java, only the lowest order bits are kept:
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.
In this case the byte 64 has the following binary representation:
01000000
The shift operator promotes the value to int:
00000000000000000000000001000000
then left shifts it by 2 bits:
00000000000000000000000100000000
We then cast it back into a byte, so we discard all but the last 8 bits:
00000000
Thus the final byte value is 0. However, your integer keeps all the bits, so its final value is indeed 256.
In java, ints are signed. To represent that, the 2's complement is used. In this representation, any number that has its high-order bit set to 1 is negative (by definition).
Therefore, when you left-shift a 1 that is on the 31st bit (that is the one before last for an int), it becomes negative.
i = a << 2;
in memory:
load a (8 bits) into regitry R1 (32 bits)
shift registry R1 to the left two position
assign registry R1 (32 bits) to variable i (32 bits).
b = (byte)(a << 2);
in memory:
load a (8 bits) into regitry R1 (32 bits)
shift registry R1 to the left two position
assign registry R1 (32 bits) to variable b (8 bits). <- this is why cast (byte) is necessary and why they get only the last 8 bits of the shift operation
The exact meaning of shifting bits is exactly what it sounds like. :-) You shift them to the left.
0011 = 3
0011 << 1 = 0110
0110 = 6
You should read about different data types and their ranges in Java.
Let me explain in easy terms.
byte a=64,b;
int i;
i=a << 2;
b=(byte)(a<<2);
'byte' in Java is signed 2's complement integer. It can store values from -128 to 127 both inclusive. When you do this,
i = a << 2;
you are left shifting 'a' by 2 bits and the value is supposed to be 64*2*2 = 256. 'i' is of type 'int' and 'int' in Java can represent that value.
When you again left shift and typecast,
b=(byte)(a<<2);
you keep your lower 8 bits and hence the value is 0.
You can read this for different primitive types in Java.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Can someone please explain why this following statement:
short value = (short) 100000000;
System.out.println(value);
Gives me:
-7936
Knowing that the maximum value of a short in Java is 32767 correct?
With your value of 100 million, I get -7936. I can only get 16960 if I change 100 million to 1 million.
The reason is that short values are limited to -32768 to +32767, and Java only keeps the least significant 16 bits when casting to a short (a narrowing primitive conversion, JLS 5.1.3). Effectively this operation: 1 million mod 2^16 (16 bits in a short) is 16960.
The way you did it merely reinterprets a smaller number of bits at the same memory location. It does not change them.
You probably want to use the max and min functions to detect when the value lies beyond of short and assign the max or min value of the short when that happens.
int n = 1000000;
short value = n > Short.MAX_VALUE ? Short.MAX_VALUE : n < Short.MIN_VALUE ? Short.MIN_VALUE : (short)n;
Update: more compactly:
import static java.lang.Math.max;
import static java.lang.Math.min;
// ...
value = (short)min(max(value, Short.MIN_VALUE), Short.MAX_VALUE);
System.out.println(value);
Here's good article explaining narrowing and widening primitive conversions in Java.
short s = 696; // 0000 0010 1011 1000
byte x = (byte)s;
System.out.println("byte x = " + x);
Produces:
byte x = -72
Now you should understand why - because when we narrow short down to
the byte the JVM discards the most significant part (00000010) and the
result (in binary form) is 10111000. This is the same number we were
looking at before. And, as you can see, it is negative, unlike the
original value.