63

I have some code like this:

class Foo {
    public double x;
}

void test() {
    Foo foo = new Foo();

    // Is this a valid way to test for zero? 'x' hasn't been set to anything yet.
    if (foo.x == 0) {

    }

    foo.x = 0.0;

    // Will the same test be valid?
    if (foo.x == 0) {

    }
}

I basically want to avoid a divide-by-zero exception in the future.

Thanks

user291701
  • 38,411
  • 72
  • 187
  • 285
  • 20
    Why don't you try it? – nanofarad Aug 15 '13 at 19:28
  • 1
    The default value of a numerical data type is 0, so yes. – Josh M Aug 15 '13 at 19:29
  • 2
    There is positive and negative zero and `x == 0` tests for both and will never give you an exception or error. You only get a divide by zero error to you divide two *integers* and the denominator is 0. Since you are using floating point, you will never get an exception. – Peter Lawrey Aug 15 '13 at 21:02
  • "'x' hasn't been set to anything yet". Yes it has. It is a member variable, so it is set to zero by default. – user207421 Aug 16 '13 at 00:20

5 Answers5

68

Numeric primitives in class scope are initialized to zero when not explicitly initialized.

Numeric primitives in local scope (variables in methods) must be explicitly initialized.

If you are only worried about division by zero exceptions, checking that your double is not exactly zero works great.

if(value != 0)
    //divide by value is safe when value is not exactly zero.

Otherwise when checking if a floating point value like double or float is 0, an error threshold is used to detect if the value is near 0, but not quite 0.

public boolean isZero(double value, double threshold){
    return value >= -threshold && value <= threshold;
}
Pimgd
  • 5,983
  • 1
  • 30
  • 45
William Morrison
  • 10,953
  • 2
  • 31
  • 48
  • 6
    +1 for making it clear that only class scope numeric primitives are initialized to zero. – anubhava Aug 15 '13 at 19:38
  • 5
    How fine one should define an error threshold ? It is very subjective and probably would not do what the user is trying to do. What if threshold is too big and you actually treat a non-zero as a zero ? – Anshul Aug 15 '13 at 19:38
  • @Anshul Whoops, thanks for the criticism! I've edited my answer after re-reading the question. Missed he was worried about division by 0. – William Morrison Aug 15 '13 at 19:43
  • "if(value != 0)" doesn't work, I have value = 0.0 and this if statement pass, and I get division by zero. – Max Husiv Jul 11 '17 at 13:32
  • @MaxHusiv In Java, I assure you checking for zero in the way I've suggested does indeed prevent division by zero. Respectfully, I expect the fault is in your code. If you can provide your code I'd be happy to assist further. – William Morrison Jul 11 '17 at 15:03
  • Sonar will complain about this: `if(value != 0)` – ACV Oct 19 '17 at 16:51
  • @ACV Checking a floating-point value against precisely zero is risky due to floating-point error involved in floating-point operations; I'd speculate Sonar is warning about this for that reason. However, to prevent a divide by zero error this is acceptable (even advisable.) – William Morrison Oct 20 '17 at 11:54
  • how it using? Where is example? What is the threshold? What a hell – Georgiy Chebotarev Sep 05 '18 at 15:49
  • 1
    Note that both `0.0 == 0.0` and `-0.0 == 0.0` return `true` and `Double.compare(0.0, 0.0)` returns `0`, while `Double.compare(-0.0, 0.0)` returns `-1`. Choose your strategy carefully. – Hummeling Engineering BV Sep 07 '18 at 12:51
12

Yes; all primitive numeric types default to 0.

However, calculations involving floating-point types (double and float) can be imprecise, so it's usually better to check whether it's close to 0:

if (Math.abs(foo.x) < 2 * Double.MIN_VALUE)

You need to pick a margin of error, which is not simple.

Community
  • 1
  • 1
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Not true only PRIMITIVES default Double (whereas this is double) would be null – Jackie Aug 15 '13 at 19:31
  • @Jackie Double is not a numeric type. – arshajii Aug 15 '13 at 19:32
  • What do you mean by numeric type? Are you trying to say primitive? – Jackie Aug 15 '13 at 19:32
  • @Jackie: Yes, except `boolean`. – SLaks Aug 15 '13 at 19:33
  • Ok but there is no "numeric" type just primitives. primitives that represent a numerical value maybe. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html – Jackie Aug 15 '13 at 19:35
  • Good catch for understand that "==" is not the right approach for floating-points – Roee Gavirel Jul 12 '15 at 11:44
  • Shy do you multiply Double.MIN_VALUE by 2? Won't it underflow because there is no other datatype to hold such a small value? In theory `2 * Double.MIN_VALUE` should return `Double.MIN_VALUE` – ACV Feb 08 '19 at 11:31
  • @ACV: You're misunderstanding MIN_VALUE. https://stackoverflow.com/q/3884793/34397 – SLaks Feb 08 '19 at 15:42
  • @SLaks no you're misunderstanding my question. MIN_VALUE is the smallest positive number that can be represented with a double. I asked why did you multiply it by 2. My misunderstanding was that I thought you raised it to power 2. – ACV Feb 10 '19 at 12:37
9

In Java, 0 is the same as 0.0, and doubles default to 0 (though many advise always setting them explicitly for improved readability). I have checked and foo.x == 0 and foo.x == 0.0 are both true if foo.x is zero

AlbertGarde
  • 369
  • 1
  • 13
  • 3
    I usually find explicitly setting a variable to its default value instead of improving readability does the exact opposite and actually decreases readability and clutters up the code. It is extraneous and isn't needed. – Michael Aug 15 '13 at 19:49
  • @PenguinAgen more explicit with 0.0d – Gaurav Jan 31 '22 at 09:50
3

Yes, it's a valid test although there's an implicit conversion from int to double. For clarity/simplicity you should use (foo.x == 0.0) to test. That will hinder NAN errors/division by zero, but the double value can in some cases be very very very close to 0, but not exactly zero, and then the test will fail (I'm talking about in general now, not your code). Division by that will give huge numbers.

If this has anything to do with money, do not use float or double, instead use BigDecimal.

Xabster
  • 3,710
  • 15
  • 21
0
  // The float data type is a single-precision 32-bit IEEE 754 floating-point number, which has a precision of approximately 6-7 decimal digits.
  public static boolean isZero(float val) {
    return Math.abs(val) < 1e-6;
  }

  // The double data type is a double-precision 64-bit IEEE 754 floating-point number, which has a precision of approximately 15-16 decimal digits.
  public static boolean isZero(double val) {
    return Math.abs(val) < 1e-15;
  }
Kaibo
  • 1
  • 1
  • 1
    So you are basically explicitly providing a "threshold" as indicated in the other answers. Maybe you could [edit] your answer and explain why the threshold you chose is a good one? – Abra Jul 19 '23 at 07:06
  • seems to be a good advice – Kaibo Aug 04 '23 at 14:17