in reply to Okay! What!?!?!?
On my system (Perl5.18.2):
#!/usr/bin/env perl printf "%.49f\n", 14.4; printf "%.49f\n", 10 + 14.4 - 10;
...outputs...
14.4000000000000003552713678800500929355621337890625 14.3999999999999985789145284797996282577514648437500
And (GNU C++).....
#include <iostream> #include <iomanip> using namespace std; int main () { cout << setprecision(51) << endl; cout << 14.4 << endl; cout << 10 + 14.4 - 10 << endl; return 0; }
...outputs...
14.4000000000000003552713678800500929355621337890625 14.39999999999999857891452847979962825775146484375
And (GNU C)
#include <stdio.h> int main (void) { printf("%.49f\n", 14.4); printf("%.49f\n", 10.0 + 14.4 - 10.0); return 0; }
...produces this output:
14.4000000000000003552713678800500929355621337890625 14.3999999999999985789145284797996282577514648437500
This is because the decimal value 14.4 cannot be perfectly represented as a fraction in the form of n/(2^m), and therefore has a non-terminating binary expansion.
The code I've shown above is first Perl, and second C++, and the third, C, just to illustrate that this is not a problem specific to just Perl. Here's yet another link that attempts to explain it: Re: shocking imprecision
Update: Here's a Lisp (Racket, a Scheme derivative) example as well:
#!/usr/bin/env racket #lang racket (displayln (~a 14.4 #:width 15 #:pad-string "0")) (displayln (~a (- (+ 10 14.4) 10) #:width 15 #:pad-string "0")) (= 14.4 (- (+ 10 14.4) 10))
...outputs...
14.400000000000 14.399999999999 #f
(The "#f" means "false"; 14.40 doesn't equal 14.399...)
JavaScript (minimal example):
alert(10+14.4-10);
The pop-up displays: "14.399999999999999"
Python:
>>> print "%.49f"%14.4 14.4000000000000003552713678800500929355621337890625 >>> print "%.49f"%(10+14.4-10) 14.3999999999999985789145284797996282577514648437500
Ruby:
$ ruby -e 'printf "%.49f\n%.49f\n",14.4, 10+14.4-10' 14.4000000000000003552713678800500929355621337890625 14.3999999999999985789145284797996282577514648437500
SQL (sqlite):
sqlite> select 14.4 - (10 + 14.4 - 10); 1.77635683940025e-15
Couldn't remember enough Pascal. "Go" must optimize away the math, because while it does produce an imprecise representation of 14.4, it produces the same imprecise representation for both 14.4, and 10+14.4-10. (GO):
package main import "fmt" func main() { fmt.Printf("%.49f\n",14.4) fmt.Printf("%.49f\n", 10+14.4-10) } --------- 14.4000000000000003552713678800500929355621337890625 14.4000000000000003552713678800500929355621337890625 Program exited.
Update: I left out Java because node lengths at PerlMonks are restricted to 64k (j/k -- I just don't know any Java)
Dave
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Okay! What!?!?!?
by tobyink (Canon) on Apr 23, 2014 at 11:27 UTC | |
by tye (Sage) on Apr 23, 2014 at 14:32 UTC | |
by davido (Cardinal) on Apr 23, 2014 at 14:11 UTC | |
|
Re^2: Okay! What!?!?!?
by trizen (Hermit) on Apr 23, 2014 at 14:45 UTC | |
|
Re^2: Okay! What!?!?!?
by karlgoethebier (Abbot) on May 01, 2014 at 14:36 UTC |