## lua "for" loop broken

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

code:
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)

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

Offline
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... :)

Offline
Joined: 05/21/2010
Groups: Go Science
 Status: Open » Closed

Closing as "not a bug"

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.