Laurent_R
Veteran
/ Moderator
Nov 17, 2012, 5:38 AM
Post #2 of 4
(22835 views)

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.66453525910038e15; similarly, ($n  2) will print as 8.88178419700125e16 (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.5527136788005e15, 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: prints, on my computer, not 0 but: 1.11022302462516e16 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: to something like this:
my $epsilon = 1e14; # define the largest deviation you are ready to accept if (abs($m5) < $epsilon) { print "$i,chenggong"; exit; } Your can read more on the subject in many places, including, for example, "What Every Programmer Should Know About FloatingPoint Arithmetic or Why don’t my numbers add up?" : http://floatingpointgui.de/ Or: https://docs.google.com/viewer?a=v&q=cache:xQj4dpk83JkJ:perso.enslyon.fr/jeanmichel.muller/goldberg.pdf+&hl=en&gl=fr&pid=bl&srcid=ADGEESjj8O_ATG0QmdQWjLuRvOdHzHkpIJzSh15a0fh9gSJgBS0kXLMN9h5nsH3mWjdGVbKasYIzo0NFDpLWbJ5qXUFaBLfA1ibPGOq5_wbGAIVuLaE4YdPnPnOADLJ7PhPQBEWXs&sig=AHIEtbTO8bIS2kWBK3Dt04BDli2I6ZQ
(This post was edited by Laurent_R on Nov 17, 2012, 5:41 AM)
