Incorrect Multiplication Result [duplicate] - java

This question already has answers here:
1000 * 60 * 60 * 24 * 30 results in a negative number [duplicate]
(4 answers)
Closed 8 years ago.
I'm trying to understand why this multiplication results in an incorrect value:
long max = (60 * 24 * 60 * 60 * 1000);
This should = 5,184,000,000
But in my Java program it = 889,032,704
Any idea why this is the case?

All of the values you're multiplying are ints so the result is an int which is cast to a long after overflow has already happened. Make one of the factors a long so that they are multiplied using 64b instructions
Try
long max = (60L * 24L * 60L * 60L * 1000L);
The L suffix specifies that the constant is a long value, not an int constant.
The language specification says
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).
and the section on multiplication says
The type of a multiplicative expression is the promoted type of its operands.
and type promotion of two ints leaves them as ints:
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

This is due to integer overflow. Your right-side product is represented as int (default type of all operands) and it obliviously can't hold your "long" value.
Just make the first factor of your product long, either as long constant 60L, as in Mike's answer, or cast it explicitly (long) 60 :
long max = (long) 60 * 24 * 60 * 60 * 1000;
and you will get what you expect.

Related

Android studio warns about integer multiplication implicitly cast to long. How to fix this?

private static boolean isOverDate(long targetDate, int threshold) {
return new Date().getTime() - targetDate >= threshold * 24 * 60 * 60 * 1000;
}
I am using above function and Android Studio warns me about:
threshold * 24 * 60 * 60 * 1000: integer multiplication implicitly cast to long
How to fix this? And why it warns?
OK, so this is a bit complicated to unpick.
On the LHS (left hand side) of the >= expression we have:
new Date().getTime() - targetDate
The type of that expression is long because targetDate is declared as long.
On the RHS we have:
threshold * 24 * 60 * 60 * 1000
That is an int because all of the operands are ints.
However that expression is likely to overflow. The value of 24 * 60 * 60 * 1000 is a "rather large", and when you multiply it by threshold, the resulting value is liable to be too big to represent as an int. If it does overflow, then the result will be truncated, and the >= test will give the wrong result.
So ... the compiler is suggesting that you should do the RHS calculation using long arithmetic. The simple way would be to declare threshold as a long. But you could also cast it to a long as in:
((long) threshold) * 24 * 60 * 60 * 1000
Since max_int is 2 147 483 648.
If your threshold is more than 25 (25 * 24 * 60 * 60 * 1000 = 2.160.000.000), it will higher than int can hold. So you will need to cast to long or the result may be incorrect.
Reference: https://stackoverflow.com/a/42671759/4316327
If an integer multiplication overflows, then the result is the
low-order bits of the mathematical product as represented in some
sufficiently large two's-complement format. As a result, if overflow
occurs, then the sign of the result may not be the same as the sign of
the mathematical product of the two operand values.
Solution:
long timeToCheck = threshold * 24 * 60 * 60 * 1000L;
return new Date().getTime() - targetDate >= timeToCheck;
or single line (different here is L after last number, it will understand that you will change type to long)
return new Date().getTime() - targetDate >= threshold * 24 * 60 * 60 * 1000L;
or casting
return new Date().getTime() - targetDate >= (long) threshold * 24 * 60 * 60 * 1000;

how does java define the result of an arithmetic expression

I am writing a parser for Java however, I am a little lost when it comes to operations on primitive types.
For example i have these expressions:
int i;
long l;
float f;
short s;
byte b;
//this is being cast from a float to an int? should this be a cast from byte?
int var1 = (int) (l * i * f * s * b);
//this is being cast from a float to an int? should this be a cast from long?
int var2 = (int) (l * (i * f * s * b));
//again casting from float to int? should this be a cast from short?
int var3 = (int) ((f) * (l) * (s));
//this seems to be a float but i expected this to be a long
int var4 = (int) ((f) * (l));
I believed that the last operation to be done would be the resulting type, however, this doesn't seem to be the case as in the above examples. (I have not listed any operations with doubles, however, it seems that a double takes precedence like float does.)
My other thinking, is that as it has to do floating point arithmetic, it is converting it to the largest (32/64)bit type so that no information is lost unless a there is a specific cast hiding the fact that it was a float/double, for example the following expression evaluates to a long.
int var1 = (l * i * (int) d * s * b);
This thinking does fall short, however, as if there is a long/float in the same expression it is somewhat likely that you will loose information if the value of the long is too large to fit into a float.
The two most relevant details, which you can find in the language spec, are:
Multiplication (and addition, subtraction, division etc) is left-associative. So:
l * i * f * s * b
is evaluated as
(((l * i) * f) * s) * b
The operands of the multiplication (and addition, subtraction, division etc) undergo binary numeric promotion. Loosely, this means that operands are widened to be compatible with each other.
More precisely:
If one operand is a double, the other is widened to double
Otherwise, if one operand is a float, the other is widened to float
Otherwise, if one operand is a long, the other is widened to long
Otherwise, both operands are widened to int
The last point tells you that even when multiplying like types, say, short and short, the operands are still widened to int
With these two points:
l * i is a long
(l * i) * f is a float
((l * i) * f) * s is a float
(((l * i) * f) * s) * b is a float.
So, you are casting from float to int.

How to calculate output of an Overflow value

I have been asked a question in Interview which was related to Integer overflow. The question was simple but I could not find a an easy solution to count the result of overflowed value.
For Example, Following program should print 1000 as output but it prints 5 due the Integer overflow.
public class IntegerOvewflow {
/**
* Java does not have target typing, a language feature wherein the type of the
* variable in which a result is to be stored influences the type of the
* computation.
*
* #param args
*/
public static void main(String[] args) {
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
}
}
But, here can we use any specific formula or equation to calculate the output of overflowed value. Here the number is really big and not easy to judge the output quickly by human mind.
Specify that they are long with L, because if not you're doing int multiplication which results in an int which touch the overflow and then store into a long
public static void main(String[] args) {
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000L;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY); // 1000
}
Check out : https://ideone.com/5vHjnH
This is the classic Problem from the very good book , Java Puzzlers Link to Book
Puzzle 3: Long Division
This puzzle is called Long Division because it concerns a program that divides
two long values. The dividend represents the number of microseconds in a day;
the divisor, the number of milliseconds in a day. What does the program print?
public class LongDivision {
public static void main(String[] args) {
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
}
}
Solution 3: Long Division
This puzzle seems reasonably straightforward. The number of milliseconds per
day and the number of microseconds per day are constants.
For clarity, they are expressed as products.
The number of microseconds per day is (24 hours/day · 60
minutes/hour · 60 seconds/minute · 1,000 milliseconds/second · 1,000 microseconds/millisecond).
The number of milliseconds per day differs only in that it is
missing the final factor of 1,000. When you divide the number of microseconds
per day by the number of milliseconds per day, all the factors in the divisor cancel
out, and you are left with 1,000, which is the number of microseconds per millisecond. Both the divisor and the dividend are of type long, which is easily large
enough to hold either product without overflow.
It seems, then, that the program
must print 1000. Unfortunately, it prints 5. What exactly is going on here?
The problem is that the computation of the constant MICROS_PER_DAY does
overflow. Although the result of the computation fits in a long with room to spare,
it doesn’t fit in an int. The computation is performed entirely in int arithmetic,
and only after the computation completes is the result promoted to a long. By
then, it’s too late: The computation has already overflowed, returning a value that
is too low by a factor of 200. The promotion from int to long is a widening primitive conversion [JLS 5.1.2], which preserves the (incorrect) numerical value. This
value is then divided by MILLIS_PER_DAY, which was computed correctly because
it does fit in an int. The result of this division is 5.
So why is the computation performed in int arithmetic? Because all the factors that are multiplied together are int values. When you multiply two int values, you get another int value. Java does not have target typing, a language
feature wherein the type of the variable in which a result is to be stored influences
the type of the computation.
It’s easy to fix the program by using a long literal in place of an int as the
first factor in each product. This forces all subsequent computations in the expression to be done with long arithmetic. Although it is necessary to do this only in
the expression for MICROS_PER_DAY, it is good form to do it in both products. Similarly, it isn’t always necessary to use a long as the first value in a product, but it is good form to do so. Beginning both computations with long values makes it clear that they won’t overflow.
This program prints 1000 as expected:
public class LongDivision {
public static void main(String[] args) {
final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
}
}
The lesson is simple: When working with large numbers, watch out for
overflow—it’s a silent killer. Just because a variable is large enough to hold a
result doesn’t mean that the computation leading to the result is of the correct
type. When in doubt, perform the entire computation using long arithmetic.
The lesson for language designers is that it may be worth reducing the likelihood of silent overflow. This could be done by providing support for arithmetic
that does not overflow silently. Programs could throw an exception instead of
overflowing, as does Ada, or they could switch to a larger internal representation
automatically as required to avoid overflow, as does Lisp. Both of these
approaches may have performance penalties associated with them. Another way
to reduce the likelihood of silent overflow is to support target typing, but this adds
significant complexity to the type system [Modula-3 1.4.8].
You can use BigInteger class for exactly these purposes.
Oracle documentation: here
There is a good quick article in this link

how to get number of micro seconds in a day

I want to get the number of micro seconds in a day
so I tried as per below
long microDay = 24 * 60 * 60 * 1000 * 1000;
for which I am expecting value as 86400000000 but when I print it
System.out.println(microDay);
The value is 500654080
After spending 3 hours and breaking my head to know the reason,final I found that java think 24,60 and 1000 as int values and int*int =int but the maximum value of int is 2147483647 so it cant store 86400000000 and hence it the output is 500654080 (but I am not sure)
In the second case I wanted to calculate miliseconds in a day and the formula goes like this
long miliDay = 24 * 60 * 60 * 1000;
System.out.println(miliDay );
output 86400000
now when I did
System.out.println(microDay/ miliDay);
output 5
but when I tried this in a calculator 500654080/86400000= 5.794607407407407
why there is different in result?
You're performing 32-bit integer arithmetic, as every operand in 24 * 60 * 60 * 1000 * 1000 is an int... but the result is bigger than Integer.MAX_VALUE, so it's overflowing (just as you suspected). (This is actually happening at compile-time in this case, because it's a compile-time constant, but the effect is the same as if it happened at execution time.)
Effectively, each operation is truncated to 32 bits. As it happens, only the final multiplication by 1000 takes the result over 231 - 86400000 is fine.
86400000000 in binary is:
1010000011101110101110110000000000000
^
\- Bit 33
So after overflow, we just chop any leading bits until we've got 32:
00011101110101110110000000000000
And that value is 500654080.
Just use long instead, e.g.
long microDay = 24L * 60L * 60L * 1000L * 1000L;
(You definitely don't need all those constants to be of type long, but being consistent means it's obvious that all the operations will be performed using 64-bit arithmetic, with no need to consider associativity etc.)
A better approach, however, would be to use TimeUnit:
long microDay = TimeUnit.DAYS.toMicroseconds(1);
As for the division part, you're performing integer division - so the result is the integer part, rounded towards 0. If you want floating point arithmetic, you need to cast one of the operands to float or double... although if you start off with the right values, of course, you should get an exact integer anyway (1000).
For the first part, put a "L" at the end of one (or more) of the constants and Java will then use long arithmetic. e.g.
long microDay = 24L * 60 * 60 * 1000 * 1000;
Addendum: Why did you get 500654080?
86400000000 decimal = 141DD76000 hex.
But, the integer only holds 32 bits, which is 8 "digits". So you lose the leading 14 and retain 1DD76000 hex.
Converting that to decimal gives 500654080.
As for the division, when you divide ints by ints (or longs by longs) Java returns the result as an int or long, so it has to truncate (or round, but Java chose to truncate) the result to 5 instead of 5.7946... Force it to do floating point arithmetic by casting one of the values to a double, e.g.
System.out.println((double)microDay/ miliDay);
When you are performing a division between 2 integers, the results are an integer. The results of the arithmetic operation will be rounded down to the nearest integer.
int i = 5 / 2; // 2.5 is rounded down to 2
if you want the output to include the decimal precision, you will need to use a different primitive data type and explicitly specify your operands to be doubles.
double j = 5 / 2; //2.0 as 5 / 2 yields and integer 2 which will be casted to a double
double j = 5 / 2.0; //2.5 explicit usage of a double will tell the compiler to return the results in double
The nuclear operations inside
long microDay = 24 * 60 * 60 * 1000 * 1000;
are all Integers specific. Max value of Integer object is 2147483647. Which exceeds the original output which is long.
Simply specifying long to variable doesn't mean all operations using [ * ] will be done using long instances. All operations done in assignment became sort of truncated.
Solution is to explicitly specify that all nuclear operations should happen over long instance and not int instances.
long microDay = 24L * 60L * 60L * 1000L * 1000L;

What is difference between Long object and primitive type long in Java?

I thought long and Long class are more or less same thing.
I saw this link
When I displayed Long.MAX_VALUE it displayed 9223372036854775807.
But when I was doing multiplication of 1000000*1000000 which is 10^12 ; it gave overflow.
I was using long data type to store value...and while debugging it had value -727379968 after multiplication
Where am I making mistake or I am totally dumb?
Update: This was my code, and I got my mistake as specified in answer.
for (;;)
ppltn[i] = Integer.parseInt(tk.nextToken());
for (int i = 0; i < noc; i++) //sum is of long type
sum = sum + min * ppltn[i]; //min and ppltn are of integer type
The expression
1000000 * 1000000;
is integer multiplication as both operands are integers. Therefore you are limited by the max value of an integer.
You need to do long multiplication
1000000L * 1000000 /* L if you want it*/;
where at least one operand is a long and the other gets promoted to a long (if it isn't already).
In Java, ^ doesn't mean "power". It is a bitwise XOR operator.
therefore 10^6 means 10 XOR 6 instead 10 * 10 * 10 * 10 * 10 * 10
it is hard to guess without seeing your code.
However my guess is you are doing somehting like
long l = 1000000 * 10000000;
If so, here is the problem.
literal 1000000 is in fact an int instead of long, and therefore, 1000000 * 10000000 is doing a int multiplication and it got overflow (max of int is something around 2,xxx,xxx,xxx). The "overflowed" value is then cast to a long. Which give you the "strange" result.

Categories