by elfpen (Novice)
 on Oct 31, 2011 at 14:56 UTC Need Help??
elfpen has asked for the wisdom of the Perl Monks concerning the following question:

What's up with this?:
```\$i = -53.80;
\$j = 46.70;

\$k = \$i + \$j;

printf "i \$i j \$j k \$k\n";

--- output ---

i -53.8 j 46.7 k -7.09999999999999

```
There's no multiplication or division. I'm able to get around it by using
`sprintf "%.2f", \$k;`
But it did catch me by surprise.

Replies are listed 'Best First'.
by Marshall (Abbot) on Oct 31, 2011 at 15:04 UTC
A floating point number will be internally represented by a mantissa and an exponent. This is of course in base 2. The fractional parts of the numbers you show cannot be represented exactly in base 2. Hence there are more binary digits than there are decimal digits and some precision is lost in the conversion process. This is normal. Your solution is the right way to do this.
by davido (Archbishop) on Oct 31, 2011 at 16:06 UTC

This question comes up frequently, and not just on Perl websites. The last time I saw the question I spent some time working on a response with the goal of it being more approachable than the standard "What every computer scientist..." article is. I'm so glad I don't have to type it all over again.

Here's a link to my previous post on the topic: Re: shocking imprecision.

Dave

Here's an example of how to use bigrat to solve the problem outside of Perl 6 Re:shocking imprecision (also in a reply to shocking imprecision).
by moritz (Cardinal) on Oct 31, 2011 at 15:08 UTC

FWIW Perl 6 solves this problem by doing math in rational numbers by default:

```\$ perl6 -e 'say -53.80 + 46.70'
-7.1
by tye (Sage) on Oct 31, 2011 at 17:22 UTC

You might want to request that your build of Perl get a different number of digits declared as "worth worrying about". Your addition only removes a single digit from the magnitude of the numbers involved. That should not, IMHO, be enough to trigger the showing of such noise.

It would probably be better for your version of Perl to be built to consider 13 digits (or maybe 14) as worth reporting instead of 15.

It looks like modern C compilers define DBL_DIG and Perl defaults to using that when converting a double into a string. Standard "double" has 52 bits of mantissa which gives 15.65 digits of accuracy (not 15.95 like wikipedia seems to claim, including the sign bit in the calculation for unknown reasons). My C compiler defines 15 for DBL_DIG, which makes sense. But Perl should not be caring about so many digits. We need only about 1/2 of a digit of error for "9999999" or "0000001" noise to start showing up.

I would want at least 1.5 digits of slush before such noise results so I would hope that Perl would default to using DBL_DIG-1 (DBL_DIG-2 seems even better) not DBL_DIG (for NV_DIG when NV is a "double").

- tye

It's not the sign bit that's included, it's the implied leading bit (0 when e==0, 1 when e!=0).

Oh, right. Thanks! So that makes it 0.95 digits of "room". (Still clearly not enough, IMHO.)

- tye

Create A New User
Node Status?
node history
Node Type: perlquestion [id://934897]
Approved by marto
Front-paged by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2018-04-21 18:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (81 votes). Check out past polls.

Notices?