3
double d= 10/3.0f;   // returns 3.3333332538604736;
float f= 10/3.0f;    // returns 3.3333333;
System.out.println(d-f);  //returns 0  ;
System.out.println(d==f);  //returns true;

is there a range after the decimal up to which the jvm checks the difference between numbers, and if so, what is that range and why?

4 Answers4

2

According to the JLS Section 15.21.1,

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).

This means that f in the expression f==d will be converted to double before doing the actual comparison.

So after 3.3333333 is turned into a double, it becomes 3.3333332538604736, which is the same as d.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
2

The key to understanding why there is no difference is to understand what this does:

double d = 10 / 3.0f;

First the 10 is promoted to 10.0f.

Next the expression 10.0f / 3.0f is evaluated to give a float value.

Finally, float value is promoted to a double and then assigned to d.

In short, 10 / 3.0f is using float arithmetic and producing a float value. And indeed, the same thing happens here:

float f = 10 / 3.0f;

except that we are skipping the promotion to a double.

Now to this:

System.out.println(d == f);

What happens here is that f is promoted to a double, and that value is then compared with d.

And ... they are the same.

Because the value of d is also produced by the same sequence of operations; see above. (It is just that the float to double promotion happens at a different point in the code.)

By the same reasoning ... in d - f, the f will be promoted before it is subtracted, and you are going to be subtracting a value from itself.


Note: the technically correct Java term for "promotion" I am talking about is a "primitive widening conversion". But that is a bit of a mouthful.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • so, does the order matter?? what i mean is had i done a comparison System.out.println( f == d ) // (instead of d == f) would there be a "demotion" of a double to float? and if that is the case, should we get a warning for "possible loss of precision" – 404 Brain Not Found Feb 14 '18 at 13:21
  • Order does not matter. The "narrower" value is promoted to the type of the "wider" value. That applies for `==` and for `/`. – Stephen C Feb 14 '18 at 13:29
  • (And for `-` ...) – Stephen C Feb 15 '18 at 00:03
  • so why does the promotion not take place when instead of doing double d = 10/3.0f; i do this... double d = 10/3.0d; in this case i get the comparison result as false. – 404 Brain Not Found Feb 17 '18 at 17:18
  • A **different** sequence happens in that case. The value 10 is promoted to a `double` and the computation is done using `double` arithmetic. The result of `double / double` is a `double` so the assignment does not require a promotion. But more important, the value is different **because the computation was done using double arithmetic**. – Stephen C Feb 17 '18 at 23:54
1

There is no range check. The values used in the subtraction and comparison are equal.

Here is why:

  • Java converts values to the same type when using operators on them. In both cases it will convert the float to a double.
  • 10/3.0f will give a float (3.3333333).
  • d will contain the value for casting the float 3.3333333 to double (3.3333332538604736).
  • Before subtracting or comparing, Java will cast the float f (which is 3.3333333) to double (3.3333332538604736), hence equal values.
Max Vollmer
  • 8,412
  • 9
  • 28
  • 43
-1

The problem you observe there is described in more detail in this post.

The core "issue" here is that in this line:

double d= 10/3.0f;

you actually cast a float to a double. If you change that to

double d= 10/3.0d;

you get the results that you've probably been looking for.

Jan Gassen
  • 3,406
  • 2
  • 26
  • 44