4

Very simple question, but I'm really confused :P

> for x = 0, 5, 0.2 do
print (x)
end

This loop counts only to 4.8 (one step more with 0.2 would result exactly 5, wouldn't it?)

But the following for-loop counts to 5

> for x = 0, 5, 1 do
print (x)
end

Can someone explain or refer to the manual, the reason behind these outputs. Maybe I should define the variable as float?

Nadeem_MK
  • 7,533
  • 7
  • 50
  • 61

4 Answers4

4

Lua usually represents numbers in ieee754 binary64 format ("usually" because the representation actually depends on the underlying C implementation). The closest number to 0.2 in binary64 is 0x3FC999999999999A, or approximately 0.200000000000000011102230246252.

The 0.2 in your source code is rounded to this number before the calculation takes place.

Since 0.200000000000000011102230246252 is larger than 2, the number becomes larger than 5 in the final step, and so the loop ends at approximately 4.8.

Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • For a detailed but gentle explanation of floating-point numbers, see [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) by David Goldberg. – Tom Blodget Sep 27 '13 at 22:03
3
for x = 0, 5, 0.2 do print (x) end

This numeric for loop will add the step 0.2 to initial value 0, do the processing (print(x)) until the value is <=5. The problem is, for floating point numbers, 0.2 can't be represented precisely, so there is a little bit rounding. So when you think it should sum as 5, it probably is a little bit bigger.

For integers that isn't very big, it can be represented precisely in a double precision floating point number, so that's no problem.


For your first day of learning Lua, a little tip:

  • Use Lua as the language name, not LUA or lua.
  • Lua has only one number type, that is double by default. * see below

*:This is no longer true. Lua 5.3 introduced a new integer subtype for numbers. See Changes in the Language

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • _Lua has only one number type, that is double by default_ - That being said, added integer support is one of the main features planned for the upcoming [Lua 5.3](http://www.lua.org/work/doc/#changes) release. – ComicSansMS Sep 27 '13 at 07:55
  • @ComicSansMS That's nice to know. I'll remember to come back here and modify the answer when Lua 5.3 releases :) – Yu Hao Sep 27 '13 at 08:03
  • @ComicSansMS, so long as it works better than the *horid* "Lua Number" patch they like to foist off on embedded ports. _*shudders*_, it tries to coerce numbers into one of a pair of hidden types and it doesn't always work, producing bizzare error messages. – Textmode Sep 28 '13 at 20:36
1

As usual, when working with floats/doubles in any language and you get some weird stuff happening, search about how floats/doubles are stored in the particular language.

This was already answered here

As @jbr already noted, 0.2 is stored as 0.2000000000000000111022302462515654042363166809082031250000000000, when a for loop runs, it checks if the value is less or equals to 5, and because the sum of these doubles is a bit greater than 5, it doesn't interpret it as a member of this loop and immediately quits.

Community
  • 1
  • 1
Sergey Telshevsky
  • 12,077
  • 6
  • 55
  • 78
1

What you are hitting here is something a lot of people get confused over in Lua. In Lua all the numbers are doubles, this means that not all number have a precise representation, 0.2 is one of those numbers:

> print(string.format("%1.64f",math.abs(0.2)))
0.2000000000000000111022302462515654042363166809082031250000000000

So what you get here is an accumulated error.

If you try 0.25:

> print(string.format("%1.64f",math.abs(0.25)))
0.2500000000000000000000000000000000000000000000000000000000000000

So

for x = 0, 5, 0.25 do
  print(x)
end

works as expected, for more information see Lua fails to evaluate math.abs(29.7 - 30) <= 0.3

Community
  • 1
  • 1
jbr
  • 6,198
  • 3
  • 30
  • 42