Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Fun with floating points

by kikuchiyo (Monk)
on Nov 06, 2009 at 13:36 UTC ( #805476=perlmeditation: print w/replies, xml ) Need Help??

I've got bitten by a peculiarity of floating point handling recently.

The phenomenon is best illustrated with the following snippet:
$ perl -le'$x=0.05;$y=sqrt($x+$x+$x);$g="$y";print "Is $y equal to $g? +";print $y==$g?"Yes":"No"' Is 0.387298334620742 equal to 0.387298334620742? No

Of course there is nothing surprising here after all. It should just serve as a reminder that floating point numbers are nasty beasts. It is dangerous to have certain assumptions about them. Also, when you write code that processes a lot of numbers then forms decisions based on comparisons ofthem, it is important to check that the code really does what you think it does. Extreme cases, loss of accuracy and so on.

Replies are listed 'Best First'.
Re: Fun with floating points
by lostjimmy (Chaplain) on Nov 06, 2009 at 17:22 UTC
    You should really be comparing floating point numbers using a threshold, rather than an absolute comparison. The problem in your code (correct me if I'm wrong) is that the representation changed when converting from a string back to a float. The following demonstrates a better way to do this.
    my $x = 0.05; my $y = sqrt($x+$x+$x); my $g = "$y"; my $h = sprintf "%.20f", $y; printf "\$y = %.20f\n\$g = %.20f\n", $y, $g; printf "\$h = %.20f\n", $h; print "Is \$y equal to \$g? ", floatEqual($y, $g) ? "Yes\n" : "No\n"; print "Is \$y equal to \$h? ", $y == $h ? "Yes\n" : "No\n"; sub floatEqual { return (abs($_[0] - $_[1]) <= 10**15); }

    I also added the $h variable, which works just fine in a direct comparison. I'm sure someone else who knows more about internal representations and conversions can shed more intelligent light on this.

Re: Fun with floating points
by Fox (Pilgrim) on Nov 06, 2009 at 14:23 UTC
    I think this is not a problem with float point numbers, but with the comparison operator:
    perl -le'$x=0.05;$y=sqrt($x+$x+$x);$g="$y";print "Is $y equal to $g?"; +print $y eq $g?"Yes":"No"' Is 0.387298334620742 equal to 0.387298334620742? Yes
      I had a reason to post it as I did.

      In the actual application where I had this issue, the workflow was something like this: data was read off from data files and stored in a Storable file. Later, these Storable files were retrieved, and the data in them was further processed. And finally I used a numerical comparison to get the result (is the number dug up from the Storable archives bigger than a pre-specified limit). However, Storable stores floating point numbers as text, at least it did in my application.

      So the real issue here is that it is awesomely convenient to have scalars-that-are-both-numbers-and-strings in Perl, but one has to be careful and know that it may lead to strange results sometimes.
        String/float conversion is not the only problem while dealing with floats. Consider following example:
        perl -e '$x=1/3; $x-=1/2; $x+=1/3; $x-=1/2; $x+=1/3; print $x,"\n"'
        $x should be equal to zero but it isn't.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://805476]
Approved by moritz
Front-paged by Arunbear
and the radiator hisses contentedly...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2017-06-22 18:41 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (526 votes). Check out past polls.