CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: General Discussions: General Questions: Re: [xiejun] a dault: Edit Log



Laurent_R
Veteran / Moderator

Nov 17, 2012, 5:38 AM


Views: 12806
Re: [xiejun] a dault

I do not understand your question, but I can tell you a couple of things about what your program does, which might actually answer your questions.

You set $s to 0.81. Then, each time through the loop, you increase it by 0.01. At one point (after 19 iterations), $s reaches 1. At this point, you have $h = 3 and $n = 2, so that $m is now 5. And it does print 5 in your example.

However, it is not exactly 5 (and it is also not exactly 3 and exactly 2). This is because floating point numbers are stored internally in floating point binary format, which cannot be (or can almost never be) an exact representation of the equivalent decimal number. Just as, in decimal numbers, 1/3 cannot be represented accurately as a decimal number: 0.33333333... If you had a computer storing internally numbers in decimal format, you would need to round off 1/3 before you could store it. This is exactly what happens here, some numbers cannot be stored accurately in the computer internal binary format and need to be round off.

When $h reaches 3, its value is not actually 3, but something extremely close to 3 (same for $n, not exactly 2). In fact, at this point, if you print $h, it will print 3; but if you print ($h - 3), you will not output 0, but something like 2.66453525910038e-15; similarly, ($n - 2) will print as 8.88178419700125e-16 (well, at least, that's what it does on my computer, you may get another result if your computer has a different architecture), and print ($m - 5) will output 3.5527136788005e-15, so, in this case, all three numbers happen to be very slightly larger than the integers you may think they are (with another example, they could have been slightly smaller, or one number larger and one smaller).

This has nothing to do with Perl, you would get similar results in C or in probably almost any language, because this has to do with the way computers are storing decimal numbers internally.

Another much simpler example of the same thing:


Code
print  0.4 + 0.2 - 0.6

prints, on my computer, not 0 but: 1.11022302462516e-16

The lesson of the story is that you should never compare for equality a floating point number and an integer.

If you really want to compare in your example, you should change:

Code
if ($m == 5)

to something like this:

Code
my $epsilon = 1e-14; # define the largest deviation you are ready to accept 
if (abs($m-5) < $epsilon) {
print "$i,chenggong";
exit;
}



Your can read more on the subject in many places, including, for example, "What Every Programmer Should Know About Floating-Point Arithmetic or Why donít my numbers add up?" :
http://floating-point-gui.de/


Or:

https://docs.google.com/viewer?a=v&q=cache:xQj4dpk83JkJ:perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf+&hl=en&gl=fr&pid=bl&srcid=ADGEESjj8O_A-TG0QmdQWjLuRvOdHzHkpIJzSh15a0fh9gSJgBS0kXLMN9h5n-sH3mWjdGVbKasYIzo0-NFDpLWbJ5qXUFaBLfA1ibPGOq5_wbGAIVuLaE4YdPnPnOADLJ7PhPQBEWXs&sig=AHIEtbTO8-b-IS2kWBK3Dt04BDl-i2I6ZQ


(This post was edited by Laurent_R on Nov 17, 2012, 5:41 AM)


Edit Log:
Post edited by Laurent_R (Veteran) on Nov 17, 2012, 5:41 AM


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives