Question about Java math operations on float
and int
data types.
I have to calculate the date difference in years between two dates.
The code:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Object date = obj.getInfoItem().getInfoValue();
Date today = new Date();
Date birthDate = null;
float dateDiff;
int age0, age1;
try {
// unify the date format
birthDate = format.parse(date.toString());
today = format.parse(format.format(today));
} catch (ParseException e) {
e.printStackTrace();
}
// calculate the age in years with round
dateDiff = today.getTime() - birthDate.getTime();
age0 = (int)((dateDiff / (24 * 60 * 60 * 1000)) / 365);
age1 = (int)(dateDiff / (365 * 24 * 60 * 60 * 1000));
Since the date difference in Java is calculated in milliseconds, thus we have to do some housekeeping work after calculation and convert received result from milliseconds to years.
After code execution, I got the following results in debugger:
dateDiff = 8.4896639E11
age0 = 26
age1 = 577
age0
is a correct result.
Since both operations on age0
and age1
are mathematically equal, why outcomes are different?
Why there is a difference between operations «(float / (a\*b\*c)) / d
» and «(float / (a\*b\*c\*d))
», where a
, b
, c
, d
are int
.
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.)