more useful options | |
PerlMonks |
Re^2: RFC: Large Floating Point Numbers - Rounding Errors (expectations)by tye (Sage) |
on Sep 09, 2011 at 18:06 UTC ( [id://925147]=note: print w/replies, xml ) | Need Help?? |
Sure. But that is worse in a lot of ways as well. What does it do to 0.0000346 ? But you can use that approach to at least very closely match (some) human expectations. It is mostly just your choice of "6" (or $n+1) that is at fault. A fairly reasonable thing to do would be more like:
Find an example that violates your expectations for that. I'll wait... The obvious one is, of course, 0.000034999999999999. But try this:
The above number is so very close to 0.000035 that Perl itself intentionally decides to display it as being exactly 0.000035. So, if that many '9's on the end doesn't violate your personal sense of perspective such that you don't mind that it gets rounded up to 0.00004, then I claim that it is your perspective when it comes to mundane computer performance that is to blame. It means that you expect your lowly computer to be able to weigh a large beach (one with 1000 volleyball courts) and not be off by a single grain of sand. Perl has this concept of "so close as to be displayed as equal" because without it you get things like sum( (0.01)x50 ) showing not as 0.5 but as 0.50000000000000022. So it is good, even important, to ignore the last several bits of floating point values when displaying them. (It is also good to do so when comparing them, but I'll just mention that can of worms without opening it.) So, why don't we just fix Perl's sprintf so 0.000034999999999999 rounds to 0.00004 ? Wait! Why should exactly 0.000035 (not floating point) round to 0.00004 ? It is exactly equally between 0.00003 and 0.00004. So either answer is equally appropriate. So always rounding such values up induces a small imbalance. That is why there is the superior "banker's rounding" where half of such values round up and half of such values round down. So, why don't we just fix Perl's sprintf so it uses banker's rounding? We don't need to:
So the real problem here is some people's naive expectations left over from 4th-grade math class, not Perl's more accurate and practical floating point behavior that it inherits from C. Banker's rounding is fine when doing calculations with pencil and paper. Let's not slow down Perl to conform to naive or out-dated human expectations. P.S. Yes, I know that 0.000034999999999999 is not the same as 0.00003499999999999999. If you didn't immediately notice the discrepancy, then I'm not surprised. The difference was intentional and, in the end, the similarity between the two seems so obvious that I decided to not even comment on it beyond this postscript. Update: The printf( "%.5f\n", sprintf("%.12e",$_) ) code neglects to insert the '1' that compensates for numbers sometimes being converted to base-2 values ever so slightly smaller than the number that the string represents. s/e/1e/i would be a reasonable way to insert that '1' but that doesn't fit easily into a simple, single-expression example. - tye
In Section
Meditations
|
|