I have the following head scratcher, demonstrated in jshell
11.0.12
and 17.0.1
here
jshell> 13.9f
$1 ==> 13.9
jshell> 13.9
$2 ==> 13.9
jshell> (double) 13.9f
$3 ==> 13.899999618530273
The same thing occurs in a simple compiled class in both versions
strictfp public class Test {
public strictfp static void main(String[] args) {
System.out.format("%s%n", (double) 13.9f);
System.out.format("%s%n", 13.9f);
}
}
╰─➤ java Test
13.899999618530273
13.9
Although 17 warns that strictfp
is no longer required
warning: [strictfp] as of release 17, all floating-point expressions are evaluated strictly and 'strictfp' is not required
The JLS says this in section 5.1.2
A widening primitive conversion does not lose information about the overall
magnitude of a numeric value in the following cases, where the numeric value is
preserved exactly:
• from an integral type to another integral type
• from byte, short, or char to a floating-point type
• from int to double
• from float to double
In 14 it contained the following after the bullet list
A widening primitive conversion from float to double that is not strictfp may
lose information about the overall magnitude of the converted value.
Based on my reading this is a bug in the implementation? The only reliable way I've found to perform this conversion is Double.parseDouble(Float.toString(13.9f))
.
CodePudding user response:
Based on my reading this is a bug in the implementation?
No. It's a bug in your expectations. The double
value you're seeing is exactly the same value as the float
value. The precise value is 13.8999996185302734375.
That's not the same as "the closest double
value to 13.9" which is 13.9000000000000003552713678800500929355621337890625.
You're assigning the value 13.8999996185302734375 to a double
value, and then printing the string representation - which is 13.899999618530273 as that's enough precision to completely distinguish it from other double
values. If it were to print 13.9, that would be a bug, as there's a double
value that's closer to 13.9, namely 13.9000000000000003552713678800500929355621337890625.