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: Perl Programming Help: Intermediate:
foreach issue

 



gipelttil
New User

Jun 2, 2014, 12:04 PM

Post #1 of 4 (6216 views)
foreach issue Can't Post

The script is as follows

perl -we '
$a=(1.9-1)/0.1;
print"$a\n";
foreach(1..$a){
print"$_ ";
}
print"\n";'


Output:
9
1 2 3 4 5 6 7 8

Why does perl interpret $a as 8 instead of 9 in the foreach loop?

Thanks a lot,


BillKSmith
Veteran

Jun 2, 2014, 12:48 PM

Post #2 of 4 (6199 views)
Re: [gipelttil] foreach issue [In reply to] Can't Post

Your problem does not have anything to do with foreach (or even with perl for that matter). Your problem is with the way that computers represent real numbers. A few of the FAQs in perlfaq4 should help you understand the problem and the recommended solution.

"Does Perl have a round function?"

"Why am I getting long decimals?"

You can read this document from your command line by typing:

Code
perldoc perlfaq4


My second reference above refers you to a lengthy document on the subject. You will be tempted to dismiss this as "More than I care to know." I recommend that you invest the effort to read it. There is a lot of math. The notation may be difficult, but the ideas are not.


Here is your script with the recommended change.

Code
#!perl -w   
$a=(1.9-1)/0.1;
$a = sprintf '%.0f', $a;
print"$a\n";
foreach(1..$a){
print"$_ ";
}
print"\n";



OUTPUT:

Code
9 
1 2 3 4 5 6 7 8 9

Good Luck,
Bill

(This post was edited by BillKSmith on Jun 2, 2014, 12:55 PM)


Laurent_R
Veteran / Moderator

Jun 2, 2014, 3:43 PM

Post #3 of 4 (6137 views)
Re: [gipelttil] foreach issue [In reply to] Can't Post

Although Bill is right and saying the right thing, I think it might be easier to grasp what is going on with the following small test with your data under the Perl debugger:


Code
  DB<50> $a = (1.9-1)/0.1; 

DB<51> printf "%.18f", $a
8.999999999999998224
DB<52>

As you can immediately see, the $a variable is not quite 9, but a floating-point number very very very slightly smaller. Now, if I convert that number to an int, this is what you get:

Code
  DB<53> print int (sprintf "%.18f", $a); 
8

And this is what is going on in your case. $a is converted to an int when you use it in a "foreach(1..$a)" type of construct.

And, as Bill said, this is not a bug of foreach, nor a bug of Perl, but this has to do with the way computers store numbers internally (binary format). Generally speaking, a number that is the result of a calculation and can be represented as an integer in decimal notation is not necessarily exactly an integer in binary notation. It might be very slightly smaller in some cases, or very slightly larger in other cases.

If you want to see a classical definitive paper on this, read this: http://www.validlab.com/goldberg/paper.pdf. Some things have changed since (64-bit machines, etc.)but the deeper problem with binary versus decimal representation has not. And, BTW, nothing to do with Perl, it is not difficult to display the same type of behavior in an Excel or Open Office spreadsheet.


gipelttil
New User

Jun 2, 2014, 5:46 PM

Post #4 of 4 (6092 views)
Re: [BillKSmith] foreach issue [In reply to] Can't Post

Thank you so much Bill. I think I learned it when I was in college. Good to have it back!

 
 


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

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