1

I'd like to check if a double is smaller, equal to, or bigger than another double. Even though I read a lot about floats and doubles not being precisely comparable because of how the computer calculates at a binary level, using the simple binary operators works like a charm so far. I tested it with dozens of different numbers and it hasn't failed me even once so far.

So is there really a problem comparing them like that in my case? And if there is - why can't I locate it and how to fix it?

EDIT: I'm aware that 0.1 + 0.2 != 0.3 if I decide to compare them. The thing is - I want to simply compare two fixed doubles. I won't have to compare 0.1 + 0.2 and 0.3. I'd have to compare 0.3 and 0.3 at best. Or 0.4 and 0.3. Something like that. Do I really need to use BigDecimal, or epsilon, or whatever for that?

user3213110
  • 199
  • 4
  • 14
  • 1
    You'll definitely run into problems if you compare with `=`. Less so with `==`, but still problematic. Also, check out http://stackoverflow.com/q/588004/1288 for one concrete example. – Bill the Lizard Apr 10 '15 at 13:45
  • possible duplicate of [Manipulating and comparing floating points in java](http://stackoverflow.com/questions/2896013/manipulating-and-comparing-floating-points-in-java) – paisanco Apr 10 '15 at 13:45
  • @BiltheLizard I've already seen that. The thing is.. I simply have two fixed(!) double numbers.. I'm not doing any operations but comperative on them. That's where my question rises from! Editted my OP as well! – user3213110 Apr 10 '15 at 13:51
  • 1
    `double`'s that really are equal will also really compare equal (except `NaN`). – harold Apr 10 '15 at 14:01
  • The `==` operator _does_ compare double values for equality. If you assign `x=0.3`, then `x == 0.3` will be `true`. All of the negative answers below are rightly warning you that programmers have _often_ introduced bugs into code by thinking of `double` as a kind of Real, and wrongly _expecting_ a particular result from some computation under some particular circumstance. (E.g., if you think that `for(x=0.0;x!=0.3;x+=0.1)` is ever going to terminate, think again!) Use `==` _wisely_, and use unit-tests and `asserts` to prove to other programmers that you knew what you were doing. – Solomon Slow Apr 13 '15 at 22:44

4 Answers4

2

doubles are a discrete representation of decimal numbers. That means that not all numbers can be represented by a double.

For example double can't represent some very large numbers accurately, in which case they are "rounded" to the closest available double. See for example:

public static void main(String[] args) {
  double d1 = 1e50;
  double d2 = d1 + 1;
  System.out.println(d2 > d1); //false
  System.out.println(d2 == d1); //true
}
assylias
  • 321,522
  • 82
  • 660
  • 783
  • @user3213110 My answer to your edit is the same: you may expect d2 to be greater than d1 in my example but it's not from Java's perspective. This may or may not be an issue for what you are doing. – assylias Apr 10 '15 at 14:06
1

Here is an example when using float can cause an error.

System.out.println(1.0 - 0.2 - 0.3 - 0.4 - 0.1); // Is not 0.0

If you need decimal numbers with arbitrary precision use BigDecimal.

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
1

The < and > operators aren't a problem.

It's the == operator that's going to create issues with any real data. So you haven't had a problem yet? Well, you can run around on a golf course during a thunderstorm waving a club over your head and not get struck by lightning, too. Doesn't mean you won't be.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
0

double's are precisely comparable. Problems arise mainly because of two reasons

  1. many people assume that math with double's works the same as math with Reals. It does not. Many assumptions about what things should be exactly equal do not easily (or at all) translate from Reals to double's.
  2. "funny things" such as Extended Precision activating unpredictably (use strictfp)

As usual, the other answers are wrong. A double does not "represent" a range of numbers (you can pretend they do, but ultimately a double only has one exact value and no notion of what sort of "range" it is meant to represent). The answer showing that equality for double's can have "funny results" is correct insofar that the result is "funny", but the problem there is with the expected result, not the result itself. If you expect the right thing, there is no problem there.

harold
  • 61,398
  • 6
  • 86
  • 164
  • Oh? Run this and tell us what you get: `#include #include #include int main( int argc, char **argv ) { uint64_t ii = UINT64_MAX; double aa = (double) ii/0.0001; ii--; double bb = (double) ii/ 0.0001; if ( aa == bb ) printf( "Hey, they're \"equal\"!\n" ); return( 0 ); }` Stating that a double value "does not "represent" a range of numbers" is disingenuous at best. For every "precise" double value, there is a range of real numbers that can only be represented by that one value. – Andrew Henle Apr 11 '15 at 00:09
  • @AndrewHenle of course there is a range of reals closest to any given double (well, except infinities and nan). This is also true of ints. That doesn't mean either of them *are* ranges, if you interpret them that way then that is merely an interpretation (and a dangerous one at that). – harold Apr 11 '15 at 11:15