Why do these two multiplication operations give different results?
long oneYearWithL = 1000*60*60*24*365L;
long oneYearWithoutL = 1000*60*60*24*365;
Your first value is actually a long (Since 365L
is a long
, and 1000*60*60*24
is an integer
, so the result of multiplying
a long
value with an integer
value is a long
value.
But 2nd value is an integer (Since you are mulitplying an integer
value with an integer
value only. So the result will be a 32-bit
integer. Now the result obtained for that multiplication
is outside the actual range of integer. So, before getting assigned to the variable, it is truncated to fit into valid integer range.
Take a look at the following print statement: -
System.out.println(1000*60*60*24*365L);
System.out.println(1000*60*60*24*365);
System.out.println(Integer.MAX_VALUE);
When you run the above code: -
Output: -
31536000000
1471228928
2147483647
So, you can see the difference..
011101010111101100010010110000000000 -- Binary equivalent of 1000*60*60*24*365L
01111111111111111111111111111111 -- Binary equivalent of Integer.MAX_VALUE
So, if you don't add that L
at the end of your number, the 4 most significant bit is removed from the first binary string..
So, the string becomes..
(0111)01010111101100010010110000000000 -- Remove the most significant bits..
01010111101100010010110000000000 -- Binary equivalent of 1471228928
(which you get as output)
UPDATE: -
From the above explanation, you can also understand that, even in the first assignment, if the result of your multiplication
of integers
before multiplying it with 365L
goes out of range, then again it will be truncated to fit in integer range, or converted to 2's complement representation
if required, and then only it will be multiplied with the long value - 365L
.
For e.g: -
long thirtyYearWithL = 1000*60*60*24*30*365L;
In the above example, consider the first part - 1000*60*60*24*30
. The result of this multiplication is: - 2592000000
. Now lets' see how it is represented in binary equivalent
: -
2592000000 = 10011010011111101100100000000000 -- MSB is `1`, a negative value
01100101100000010011100000000001 -- 2's complement representation
Decimal representation of the 2's complement
representation is 1702967297
. So, 2592000000
is converted to -1702967297
, before getting multiplied to 365L
. Now since, this value fits in the integer range
which is : - [-2147483648 to 2147483647]
, so it will not be truncated further.
So, the actual result will be: -
long thirtyYearWithL = 1000*60*60*24*30*365L;
= 2592000000 * 365L;
= -1702967297 * 365L = -621583063040
So, all these stuffs just considers the actual type
of final result on applying the arithmetic operation. And this check is performed on each temporary result of operations moving from left to right
(considering operators with left-to-right
associativity). If any temporary result is found to be out of range, then that is converted accordingly to fit in the required range, before moving forward with next operation.
UPDATE 2: -
So, instead of: -
long thirtyYearWithL = 1000*60*60*24*30*365L;
if you move your 365L
at the start, then you will get the correct result: -
long thirtyYearWithL = 365L*1000*60*60*24*30; // will give you correct result
Because, now your temporary
result will be of type long
, and is capable of holding that value.
Ints and Longs multiplication gives different answers
The max value an integer can hold is roughly 2 billion (2,147,483,648). The result of your multiplication is roughly 200 trillion (254,358,061,056,000). This is a case of integer overflow.
int * int * int
will give you an integer before it's widened to a long and assigned to the long variable.
Ints and Longs multiplication gives different answers
The max value an integer can hold is roughly 2 billion (2,147,483,648). The result of your multiplication is roughly 200 trillion (254,358,061,056,000). This is a case of integer overflow.
int * int * int
will give you an integer before it's widened to a long and assigned to the long variable.
Why does changing the sum order returns a different result?
Maybe this question is stupid, but why does simply changing the order of the elements affects the result?
It will change the points at which the values are rounded, based on their magnitude. As an example of the kind of thing that we're seeing, let's pretend that instead of binary floating point, we were using a decimal floating point type with 4 significant digits, where each addition is performed at "infinite" precision and then rounded to the nearest representable number. Here are two sums:
1/3 + 2/3 + 2/3 = (0.3333 + 0.6667) + 0.6667
= 1.000 + 0.6667 (no rounding needed!)
= 1.667 (where 1.6667 is rounded to 1.667)
2/3 + 2/3 + 1/3 = (0.6667 + 0.6667) + 0.3333
= 1.333 + 0.3333 (where 1.3334 is rounded to 1.333)
= 1.666 (where 1.6663 is rounded to 1.666)
We don't even need non-integers for this to be a problem:
10000 + 1 - 10000 = (10000 + 1) - 10000
= 10000 - 10000 (where 10001 is rounded to 10000)
= 0
10000 - 10000 + 1 = (10000 - 10000) + 1
= 0 + 1
= 1
This demonstrates possibly more clearly that the important part is that we have a limited number of significant digits - not a limited number of decimal places. If we could always keep the same number of decimal places, then with addition and subtraction at least, we'd be fine (so long as the values didn't overflow). The problem is that when you get to bigger numbers, smaller information is lost - the 10001 being rounded to 10000 in this case. (This is an example of the problem that Eric Lippert noted in his answer.)
It's important to note that the values on the first line of the right hand side are the same in all cases - so although it's important to understand that your decimal numbers (23.53, 5.88, 17.64) won't be represented exactly as double
values, that's only a problem because of the problems shown above.
Different results of different, but equal math operations on float in Java
To expand on Sotirios' comment: The integer literals 365
, 24
, 60
, and 1000
all have type int
. Therefore, multiplication will be performed using the int
type. Since the mathematical result is 31536000000, and the largest possible int
is 2147483648, the result overflows and the result will wrap around. The result will thus be the int
whose value is equivalent to 31536000000 modulo 232, which is 1471228928. Only then is it converted to a float
to be divided into dateDiff
. Appending an L
to the end of any of the integer literals will fix it, since now at least one of the multiplications will be performed using long
. But it might be clearer to change 365
to 365.0
(or 365f
). (Actually, @Chill's suggestion to use f
on all the constants appears best to me, although it's not really necessary.)
Python - Java Math operations give different results
When you do
int(math.pow(14764352724, 6))
you get a big number elevated to a power but using a floating point method, even if arguments are integers. Converting to integer loses precision (the original result is a float: 1.0358251994780843e+61
)
When you do
14764352724**6
you get a big number elevated to a power using a binary power method using only integer multiplication.
So the second result is accurate, whereas the first isn't
>>> int(math.pow(14764352724,6))
10358251994780842724998096890217137953445700726699419360034816 # wrong
>>> 14764352724**6
10358251994780842575401275783021915748383652186833068257611776 # correct
Let's try a disassembly of both **
and math.pow
functions:
import dis,math
def test(n):
return n ** 3
def test2(n):
return math.pow(n,3)
dis.dis(test)
dis.dis(test2)
output
4 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (3)
6 BINARY_POWER
7 RETURN_VALUE
7 0 LOAD_GLOBAL 0 (math)
3 LOAD_ATTR 1 (pow)
6 LOAD_FAST 0 (n)
9 LOAD_CONST 1 (3)
12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
15 RETURN_VALUE
as you see, the functions aren't equivalent. BINARY_POWER
is called in the first case. This function has a chance to perform integer multiply accurately when parameters are integer:
BINARY_POWER()
Implements TOS = TOS1 ** TOS
Binary power yields the same value as math.pow
when parameters aren't all integer:
>>> 14764352724**6.0
1.0358251994780843e+61
>>> int(14764352724**6.0)
10358251994780842724998096890217137953445700726699419360034816
Note: what probably adds to the confusion is the built-in pow
method, which is different from math.pow
(and overridden by the latter when using from math import pow
), but is equivalent to **
operator when used without modulo argument:
pow(x, y[, z])
Return x to the power y; if z is present, return x to the power y, modulo z (computed more efficiently than pow(x, y) % z). The two-argument form pow(x, y) is equivalent to using the power operator: x**y.
I can't understand why this code give me wrong results for multiplication ,division and subtraction?
You cannot "refactor" your condition x==(1||2||3||4)
You need to explicit write x == 1 || x == 2 || x == 3 || x == 4
instead.
Your compiler understands "if x
is equal to 1
OR if x
is equal to 2
, etc."
It does not understand "if x
is equal to 1
, 2
, 3
, or 4
"
Any number different from zero is considered true
, so 1||2||3||4
is the same as 1
.
If you want, you could write x >= 1 && x <= 4
. You only check the lower and upper bounds.
Also, don't forget to check that num2
is different from 0
in the case of the division. Otherwise, your program will crash.
Related Topics
How to Get the Current Time in Yyyy-Mm-Dd Hh:Mi:Sec.Millisecond Format in Java
The Performance Impact of Using Instanceof in Java
Which Cipher Suites to Enable for Ssl Socket
Jdbc Connection Failed, Error: Tcp/Ip Connection to Host Failed
Certain Unix Commands Fail with "... Not Found", When Executed Through Java Using Jsch
What's the Difference Between Primitive and Reference Types
Add Jar Files to a Spark Job - Spark-Submit
How to Get the SQL of a Preparedstatement
Java Time-Based Map/Cache with Expiring Keys
Selenium Webdriver How to Resolve Stale Element Reference Exception
Eventlistenerlist Firing Order
Java: How to Split an Arraylist in Multiple Small Arraylists
How to Specify the Schema When Connecting to Postgres with Jdbc
Interview Question: Check If One String Is a Rotation of Other String