News for hackers. Stuff that matters.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by mooism2 on Thursday October 04, 2012 @11:14AM (#4612675)
You should perhaps be using a rational number datatype instead of floating point arithmetic.

It depends what calculations you're doing: if you need to use transcendental functions then you're stuck with floating point, and you'll have to decide how close two numbers need to be for you to consider them equal. n.b. you need to do this: no programming language can know whether false positives are more or less harmful than false negatives in your program.

Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by informatimago on Friday October 05, 2012 @11:15AM (#4617214)
Indeed old programming languages get it right:

Fortran (the oldest still in use):

    $ cat sub.f
    C Prints 0.3-0.2 and 0.2-0.3
          PRINT 4, 0.3-0.2, 0.2-0.1
        4 FORMAT ('0.3-0.2=',F3.1,' 0.2-0.1=',F3.1)
          STOP 1
          END
    $ gfortran sub.f -o sub
    $ ./sub
    0.3-0.2=0.1 0.2-0.1=0.1
    STOP 1
    $ 
Lisp (the second oldest still in use):

    cl-user> (values (- 3/10 2/10) (- 2/10 1/10))
    1/10
    1/10
Cobol (the third oldest still in use):

    $ cat sub.cob
           IDENTIFICATION DIVISION.
           PROGRAM-ID. DIFFERENCE.
           ENVIRONMENT DIVISION.
           INPUT-OUTPUT SECTION.
           FILE-CONTROL.
           DATA DIVISION.
           FILE SECTION.
           WORKING-STORAGE SECTION.
           77 out32 pic 9.9.
           77 out21 pic 9.9.
           PROCEDURE DIVISION.
               subtract 0.2 from 0.3 giving out32.
               subtract 0.1 from 0.2 giving out21.
               display '; 0.3 - 0.2 = ' out32 .
               display '; 0.2 - 0.1 = ' out21 .
               goback.

    $ cobc  -fixed -Wcolumn-overflow -Wparentheses  -x sub.cob
    $ ./sub
    ; 0.3 - 0.2 = 0.1
    ; 0.2 - 0.1 = 0.1
    $
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by zerohp on Thursday October 11, 2012 @06:57PM (#4643192)
These code samples don't test equality. Printing the output probably rounds off the difference.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by anonymouz on Thursday October 04, 2012 @12:40PM (#4613132)
As many others have pointed out, this is not really a matter of language but of the data types used. In IEEE 754 floating point arithmetic, the two expressions are not equal.

You're looking for a different data type, and many choices would give you the desired equality: a decimal floating point representation, calculating with rational numbers and interval arithmetic come to mind (technically, IEEE floating point is a kind of interval arithmetic, but you have not much control over the size of the intervals used and comparison does not do what you might naively expect, i.e., checking whether the two intervals intersect).

I suppose you should look for a library like GMP or MPIR for whatever is your preferred language. Most computer algebra systems (e.g., Sage) will also provide with what you need in some way or another.

Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by beagle3 on Thursday October 04, 2012 @02:02PM (#4613508)
But the APL family (APL, J, K) does get this right despite using IEEE 754 floating point - it has comparison tolerance built in.

And you would probably look at what it does with disgust, given that it breaks transitivity of equality (that is, there are numbers such that a==b and b==c but a<>c). However, in practice it does work very well. You can still run into weird corners, but e.g.

    (3*(a/3.0))==a 
always holds true, unlike with C comparison semantics.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by anonymouz on Thursday October 04, 2012 @03:11PM (#4613827)
This seems to be a very sensible default way to handle the comparison, assuming the programmer already knows about the problems with floating point math. A programmer who does not know about that will probably trip up sooner or later no matter how the language implements comparison.

So personally I would not see it as "right" (or "wrong"), simply because it is a choice between many different methods with their own advantages and disadvantages. I view this not as a problem a language can (or has to) solve, but as one a programmer has to be aware of and has to solve depending on his particular application.

Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by shared4you on Thursday October 04, 2012 @11:36AM (#4612806)
Of course, Mathematica gets it right :) As a general rule, never use == and != operators on floats or doubles.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by Piskvorrr on Thursday October 04, 2012 @10:56AM (#4612556)
It depends on what the meaning of the word "is" is.

In other words, floating point operations in binary computers can give unintuitive results; welcome to the bizarre world of programming. This may be a useful starting point for reading: http://stackoverflow.com/questions/1167691/ieee-floating-poi... , or perhaps this: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.ht...

(Note that most programming languages have a prominent warning about this in the documentation.)

Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by d0m on Thursday October 04, 2012 @12:07PM (#4612968)
IMHO, the right thing to do would be to forbid the usage of == for decimals values.

  1.0 == 0.9 -> Throw err
  1.0 > 0.9 -> true
In most case, you don't want to use == on double because it 's very dangerous... it's way better to use (0.3 - 0.3000001) < 0.001 or something similar. So, by forbidding the == on doubles, you force the programmer to use a safer way. In the same time, it's a clean hack around this decimal issue. As a bonus, a programmer who doesn't know binaries arithmetic might get curious on why == isn't implemented on double and read on it.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by shangaslammi on Friday October 05, 2012 @02:33AM (#4615906)
In Haskell, decimal literals can be inferred as any Fractional type (including Rational, which is precise), but they default to Double if there is no context that dictates otherwise.

    Prelude> 0.3 - 0.2 == 0.2 - (0.1 :: Rational)
    True
Above, we explicitly declare one of the literals as Rational, and the rest are inferred as having the same type (since the standard library does not allow you to do arithmetics or comparisons between discrepant types).
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by draegtun on Friday October 05, 2012 @06:11AM (#4616278)
Perl6 gets it right:

  $ perl6
  > (0.3 - 0.2) == (0.2 - 0.1)
  True
Because Perl6 use Rationals by default:

  > (0.3 - 0.2).perl
  1/10
To get it to work in perl5 you need to use bigrat pragma:

  $ re.pl
  > (0.3 - 0.2) == (0.2 - 0.1)
  
  > use bigrat;
  > (0.3 - 0.2) == (0.2 - 0.1)
  1
I think Clojure is another language that uses Rationals by default.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by vec on Thursday October 04, 2012 @11:51AM (#4612875)
Hopefully none of them (at least none that use floating point arithmetic). When you convert the equation to the exponent notation you get this:

(1.2x2^-2) - (1.6x2^-3) = (1.6x2^-3) - (1.6x2^-4)

which is pretty clearly false. http://www.h-schmidt.net/FloatConverter/IEEE754.html has a pretty nice conversion tool, if you're curious.

Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by beagle3 on Thursday October 04, 2012 @12:24PM (#4613054)
APL, J and K/Kona all get it "right" - their default floating point comparison is a "tolerant comparison", basically meaning that floating point numbers compare equal even if they are slightly apart (a few ulps, configurable). It does not extend to hashing (because tolerant equality does not actually have equivalence classes), but is nevertheless an extremely useful behaviour.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by CurtHagenlocher on Thursday October 04, 2012 @11:20AM (#4612716)
I suspect COBOL got this "right"...

In C#, (0.3m - 0.2m) == (0.2m - 0.1m). The latest version of the C++ spec allows for user-defined literals, so you could do something similar there (with caveats). But as far as I know, there's no modern language in widespread use that has decimal literals which default to base-ten representations.

Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by rst on Thursday October 04, 2012 @11:52AM (#4612883)
Some SQL implementations seem to. In Postgres:

  test=# select (0.3 - 0.2) - 0.1;
   ?column? 
  ----------
        0.0
  (1 row)
(Ruby gives me -2.77555756156289e-17)
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by darkxanthos on Thursday October 04, 2012 @11:32AM (#4612780)
Oddly Javascript does. Probably more oddly I don't get why that's "right"
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by infinity on Friday October 05, 2012 @03:46AM (#4616012)
I have just tested it on a Windows Vista machine, it doesn't work in Internet Explorer, Opera and Safari. Putting each side of the equation into an alert box shows the difference.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by arcatek on Thursday October 04, 2012 @12:11PM (#4612995)
It does not in Chrome.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by S4M on Friday October 05, 2012 @06:39AM (#4616332)
I found once that 3.6 - 3*1.2 == 0 was false in C, and subsequently in all the languages I could find.

I suspect it is due to the fact that those number have an infinite binary expansion...

Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by genwin on Thursday October 04, 2012 @11:26AM (#4612742)
I checked in Go (golang). Verbatim, it's false. But if I save at least one side of the equality to a variable, or cast at least one side to a float, it's true.
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by Misiek on Tuesday October 09, 2012 @03:30AM (#4630420)
PHP (5.3):

  echo ((float)(string)(0.3 - 0.2) == (float)(string)(0.2 - 0.1)) ? 1 : 0;
  1
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by brghteyes on Thursday October 04, 2012 @12:07PM (#4612962)
bc gets it right

  $ bc -l -q
  .3 - .2 == .2 - .1
  1
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by ehutch79 on Friday October 05, 2012 @11:55AM (#4617377)
wait. why is that false? both come out to 0.1, which should be equal?
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by Breakthrough on Saturday October 06, 2012 @07:58PM (#4622163)
In binary, you can't represent any of 0.1, 0.2, nor 0.3 with "proper" fractions, as they are irrational in a radix-2 number system. Thus, when actually performing the operation (0.3 - 0.2) - (0.2 - 0.1), the result may actually be non-zero, although very small.

The best thing to do here would be to use an inline comparison function with a threshold:

    inline bool is_equal(double a, double b, double threshold = 0.0000001f)
    {
        if ( abs(a-b) < threshold )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
Unfortunately, compounding floating point operations can drastically reduce calculation accuracy, leading to requiring a greater threshold value... Which is why I highly recommend reading the article titled "What Every Computer Scientist Should Know About Floating-Point Arithmetic" by David Goldberg (circa 1991, available at http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.ht...).
Re:0.3 - 0.2 == 0.2 - 0.1 is falsy. Which language gets this... by rprasad on Thursday October 04, 2012 @12:40PM (#4613135)
Any language which uses floating points to represent these values rather than fixed points.

C# and some versions of C use fixed-point representations for these values by default (or correct for floating point errors internally, as with C#), and return the correct answer of true, as .1 is equal to .1 in fixed-point representations.

EDIT: False is only the correct answer when using floating point representations, as the equation no longer boils down to .1 == .1, but something like .999 == 1.0001, etc.