2

I ran into an issue which I was wondering if the expected behavior is correct or whether I found a bug.

Given this:

0.08 > 0.08 == false
0.08 > 0.08F == true
0.08 > 0.08F.toDouble() == true

0.08.toFloat() > 0.08F == false

Why does the third expression is not false? Any ideas?

2 Answers2

4

It is not a bug, it's based on rounding errors.

Executing the following code:

val d = 0.08
val f = 0.08F
val fd = f.toDouble()
print("%.20f".format(d) + "\n")
print("%.20f".format(f) + "\n")
print("%.20f".format(fd))

gives you the following output:

0.08000000000000000000
0.07999999821186066000
0.07999999821186066000

So as you can see, 0.08 double value is (till the 20th decimal place) exact to 0.08 while the float is (due to lower precision) not able to be represented as exact so it contains a rounded value, which is slightly lower than 0.08

Converting your approximate (a little lower) 0.08 float to a double doesn't increase your precision, you still have your rounding error of the float, which results in being the converted double to be a little bit lower.

// Edit: If you are interested in how exactly floating point numbers work, I would recommend you to have a look at the wikipedia article on floating point arithmetic and at this question: Is floating point math broken?

ich5003
  • 838
  • 1
  • 9
  • 24
  • 2
    The last link, to [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken/588014#588014), is not a good reference. The answers there are generally not tutorial and generally attempt to “explain away” errors with one rationale or another rather than giving the background and mathematical formulation that a student needs to work with floating-point arithmetic. – Eric Postpischil Mar 09 '20 at 13:52
3

This is a supplement to the existing answer. Java BigDecimal has two useful properties for analyzing floating point behavior. Conversion from float or double to BigDecimal is exact, and so is its default string conversion. The simplest use of these properties is to print the exact value of a floating point expression. BigDecimal arithmetic can also be used, for example, to find the half way points between a double and its neighbors when studying rounding.

This program:

import java.math.BigDecimal;

public strictfp class Test {
    public static void main(String[] args) {
        System.out.println(new BigDecimal(0.08));
        System.out.println(new BigDecimal(0.08f));
    }
}

outputs:

0.08000000000000000166533453693773481063544750213623046875
0.07999999821186065673828125

which confirms that 0.08 is represented to the expected precision in each format, and the double representation is strictly greater than the float.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75