lua "for" loop broken

Case number:845813-991146
Topic:Game: Tools
Opened by:Rav3n_pl
Opened on:Friday, November 25, 2011 - 22:22
Last modified:Saturday, May 29, 2021 - 20:49

for i=1,10,1 do print(i) end
output: (...)7, 8, 9, 10

for i=0.1,1,0.1 do print(i) end
output: (...)0.7, 0.8, 0.9, 1

for i=0.1,1,0.01 do print(i) end
output: (...)0.97, 0.98, 0.99 !!!! NO 1 !!!

When step is 0.08 or lower it is not doing "final" count.

(Fri, 11/25/2011 - 22:22  |  4 comments)

rmoretti's picture
User offline. Last seen 17 hours 48 min ago. Offline
Joined: 01/15/2010
Groups: Foldit Staff

This isn't actually a bug in either lua or Foldit - it has to do with how real numbers are represented in computers. (Google "What Every Computer Scientist Should Know About Floating-Point Arithmetic")

The short answer is that just like 1/3 and 1/7 can't be exactly represented as a finite-length decimal, 1/10 can't be represented as a finite length value in the binary representation that computers use. When you write "0.01" in a computer program, the computer converts this to a binary number that is almost-but-not-quite equal to 0.01. (It also "helpfully" converts the almost-but-not-quite value back to the "simple" decimal representation when printing.) So when you add them together multiple times, the errors accumulate, and you don't actually hit 1.0 on the last time, but rather a number slightly higher, which then doesn't get printed.

You can test this by using a value that can be exactly converted to binary, e.g. 1/64 = 0.015625

for i=0,1,0.015625 do print(i) end
output: (...) 0.984375, 1

The work around is to stick with iterating over integers, which can be exactly converted to binary, and then do the division afterward. That way you don't get the accumulation of small errors:

for i=10,100,1 do print(i/100) end
output: (...) 0.97, 0.98, 0.99, 1

Joined: 06/17/2010

Use BCD then and forget about binary :P
Thats why in some langs "for" can be uses only on int variables... :)

NinjaGreg's picture
User offline. Last seen 6 hours 20 min ago. Offline
Joined: 05/21/2010
Groups: Go Science
Status: Open » Closed

Closing as "not a bug"

NinjaGreg's picture
User offline. Last seen 6 hours 20 min ago. Offline
Joined: 05/21/2010
Groups: Go Science

Note: in the last example, a workaround would be to set the for loop to use 1 to 100, then divide the value by 100 if you intend to use it in the body of the loop.


Developed by: UW Center for Game Science, UW Institute for Protein Design, Northeastern University, Vanderbilt University Meiler Lab, UC Davis
Supported by: DARPA, NSF, NIH, HHMI, Amazon, Microsoft, Adobe, Boehringer Ingelheim, RosettaCommons