Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In current C++ and Java, double type and float type : if (x == 0.0) is correct? [duplicate]

In my old knowledge: when we want to check whether a double or float is equal 0.0,
we should not write like this:

double x = 0.0;
if (x == 0.0) System.out.println("yes");
else System.out.println("no");

But several minutes ago, I tried it again, under Java(1.7) and C++(Apple LLVM version 6.0), there is no problem to write like that! I have tried both "double" type and "float" type under Java and C++, respectively.

My question:

  • Did I miss something, or we really can check the double or float like that under current Java and C++.
  • If we can, whether we can do it under early version of Java and C++?


Conclusion(based on all helps):
We should not use "float == float or double == double" to check whether two floats or two doubles are equal(if we want to get the right answer), the reasons are in all answers and comments below.


Edition(First time):
Thank you so much for all help!
But one minute ago, I just try these under Java(1.7), all show "yes",
it seems we really can do it under current Java!
float x = 0.0f;
if (x == 0) System.out.println("yes");
else System.out.println("no");

float y = 100.0f - 50.0f*2.0f + 45.0f*3 - 135.0f;
if (y == 0.0f) System.out.println("yes");
else System.out.println("no");

if (100.0f - 50.0f*2.0f + 45.0f*3 - 135.0f == 0.0f) System.out.println("yes");
else System.out.println("no");


Edition(Second Time):
But I have tried this, Java also shows "yes", (under Java(1.7)).
I try to eliminate compiler's "pre-compute", and split the computation into several steps.
float a = 100.0f;
float b = 50.0f;
float c = 2.0f;
float bc = b * c;
System.out.println("b*c = " + bc);

float d = 45.0f;
float e = 3.0f;
float de = d * e;
System.out.println("d*e = " + de);

float f = 135.0f;

float g = a - bc + de - f;
float h = 0.0f;
if (g == h) System.out.println("yes");
else System.out.println("no");


Edition(Third Time):
Thank you for @DiegoBasch's counterexample (for float == float):
This time Java(1.7) shows "no".
float m = 0.37f - 0.36f;
float n = 0.01f;
if (m - n == 0.0f) System.out.println("yes");
else System.out.println("no");
like image 938
Zhaonan Avatar asked Oct 08 '14 16:10

Zhaonan


2 Answers

The code is legal. The problem is that when you're doing calculations involving floating-point numbers, there will be rounding errors, and therefore in many cases checking for exactly 0 (or checking two numbers for equality) will not work.

This code is fine in any language since you haven't done anything that would cause rounding:

double x = 0.0;
if (x == 0.0) System.out.println("yes");
else System.out.println("no");

This code may not be fine, though:

double a1 = ...something...;
double a2 = ...something...;
double a3 = a1 / a2;
double a4 = a3 * a2;
double a5 = a4 - a1;
if (a5 == 0.0) ...

Even though mathematically a5 should be 0, in practice the == operation may return false because of rounding.

This requires an understanding of how floating-point is handled in a computer; it has nothing to do with any language or version of a language. One reference is What Every Computer Scientist Should Know About Floating-Point.

like image 137
ajb Avatar answered Oct 06 '22 00:10

ajb


To complement ajb's answer, here's an example of numerical error. You don't need many calculations for it to happen.

    double a = 0.37 - 0.36; // 0.010000000000000009
    double b = 0.01;
    System.out.println (a - b == 0.0); // false
like image 36
Diego Basch Avatar answered Oct 05 '22 22:10

Diego Basch