Rounding error?

Hi,
I’m working on a pattern that involves working out angles around a circle. Most of the code is irrelevant here so I’ll just focus on this very (imo) strange behavior.

points = 8
angle = 360/points
for t = 0, 360-angle, angle do
print (t)
end

This piece of code prints out the angles equally spaced around a circle, based on number of points on circumference. So for example, if points = 8, angle will be 45, and printout will be 0, 45, 90, 135, 180, 225, 270, 315. Now for some reason, certain point values fail to print out the last angle e.g. 13, 17, 26. I thought at first it may be primes but 26 isn’t and 19 & 23 work ok.

I wondered if it was some sort of rounding discrepancy, and made this slight change…

for t = 0, 360-angle+0.0001, angle do

and it now ‘mostly’ works. However, the addition of 0.0001 fails to fix points = 26. But change it to 0.001 and that now works. So is some sort of threshold involved too?

Hope someone can shed some light on what is going on.

Many thanks,

David

Sorry… How do you stop code all appearing on one line too? ;-p

points = 8

angle = 360/points

for t = 0, 360-angle, angle do

print (t)

end

Well idk why it behaves like that… but another way of doing a function like that is…

function Angles(points)
    
    solutions = {}
    
    for i = 0, points - 1 do
        
        table.insert(solutions, 360/points * i)

    end

    return solutions
    
end

[tested]

That would stop the strange behavior since it uses the points as reference instead of the rounded angles…

@David The problem is rounding. I’m not sure of all the answers you want, but see if this helps. And to post your code correctly, put 3 ~ ( tildes) on a seperate line before and after the code.

function setup()
    points = 26
    angle = 360/points
    for t = 0, 361, angle do
        print (t)
    end
end

@David Or maybe this one.

function setup()
    points = 26
    angle = 360/points
    for t = 0, 361-angle, angle do
        print (t)
    end
end

Well I still think my solution would work for every situation, @dave1707 with your solutions, there might still be some points that will not show correctly, tho they would be rare :wink:

In a nutshell, you should try really hard to avoid iterating over non-integers. Make your loop over integers and do the maths inside. This is what @stevon8ter does. To make it like your original code, do

points = 26
angle = 360/points
for i=0,points-1 do
   print(i*angle)
end

Thanks guys, that’s really helpful. But @stevon8ter - I can’t seem to get your function to work. I typed it in followed by Angles(12) but nothing happens.

@David
make sure to put the Angles(12) in the setup, or draw , just make sure it’s called

The funtion returns a table, so you could save the table as follows

angles = Angles(12)

and to print all values you should do

for i = 1, 12 do
   print(angles[i])
end

Thanks @stevon8ter - it works but still trying to understand why…

I follow that Angles is a function with points as a parameter. Angles (12) invokes the function, so not sure what happens with angles = Angles (12)

My initial instinct was to print the values from the table within the function, like…

    function Angles(points)
    solutions = {}
    for i = 0, points - 1 do
    table.insert(solutions, 360/points * i)
 
    print(solutions[i+1])

    end

    return solutions

end

This works but I want to understand why your method works too.
So if solutions{} is a table, how are you retrieving the angles from it? Where does ‘return solutions’ actually return the solutions to?

Basically, from outside the function …

Angles(12)

for i = 1, 12 do
    print(solutions[i])
end

makes sense to me and it works. Your method works too but I’ve really no idea why. So many questions, sorry!!

Many thanks.

David

@David That last example shouldn’t work, because @stevon8ter forgot to use local.

The proper syntax should, for the function, be

function Angles(points)
    local solutions = {}
    
    for i = 0, points - 1 do
        table.insert(solutions, 360/points * i)
    end
    
    return solutions
end

This is what happens, Dave, when you don’t use local. People who learn from you don’t, in a situation that needs local, use local.

The proper syntax should, to retrieve the points, be

a = Angles(12)

for k, v in ipairs(a) do
    print(v)
end

function Angles(points) returns a table, which contains all the points it calculated. The for loop goes through all the variables in the table, printing them out. k is the index, v is the variable.

Some more info on tables can be found here.

Ok i actually have a little misstake in my function, the solutions shouldn’t be accesable like that from outside the function, so it should be

function Angles(points)
    local solutions = {}
    for i = 0, points - 1 do
    table.insert(solutions, 360/points * i)

    print(solutions[i+1])

    end

    return solutions

end

this makes that the var solutions can only be called from withing the function
tho when you want to print it from without the function… The return means that the function itself returns the value… so you could do

points = 12

for i = 1, points + 1 do
    print(Angles(points)[i])
end

Because the function itself would return the table

Tho that isn’t a good solution because it calculates the function everytime the for loop moves on

so a better solutions would be to store the table once, and then loop over the values of that table

points = 12

angle = Angles(points)

for i = 1, points + 1 do
    print(angle(points)[i])
end

this way, the table’s strored in the var ‘angle’
and is only calculated 1 time, so this would be a better solution than calling the function everytime, also, if you want to call the same function for example 10 times in your program (assuming it’s 10 times the same value)… You don’t have to calculate it 10 times, you still have that table stored :wink:

Thanks guys… I’m getting there… slowly! Just still not totally got my head around ‘return solutions’ When you say it causes the function itself to return the values, where does it put them exactly? If I do

print(solutions[1])

I get an error - attempting to index global ‘solutions’ (a nil value)

I guess I’m getting confused with putting the code inside a function. Presumably ‘local solutions’ means can only be accessed inside the function? I’ll keep researching and playing with it.

Yes local means it only can be used withing the function, and will not mess with other vars if you call one solutions… so you can still use the var ‘solutions’ without having to pay attention to the one within the function

This also means, doing ~~~ print(solutions[1]) ~~~ outside the function will give an error, since the var doesn’t really exist

if you’dd do ~~~ print(Angles(12)[1]) ~~~
it would return the first answer

But calling the function everytime you need one if the indexes, is very expansive…
Look at it this way:

Angles(4)

the functions would at the end look like this

solutions = {0, 90, 180, 270}
return solutions

so it would return a table, but as said, calling the function everytime to get to the table’s not the best way

so that’s why we put the table into another var, so we store the returned value in a var

varofmychoice = Angles(4)

eventually varofmychoice would look like:

varofmychoice = {0, 90, 180, 270}

so that’s a table… the same as solutions was…

And now you can print the values of that table

But ofcourse, if it’s only for printing those values immediatly… then you don’t have to return it, you could do everything inside the function

But the ~~~ return ~~~ … it would be good if you know what it does, since alot of people use it, alot of integrated functions as well… say that we do


that also RETURNS a value... ;)

I hope it's clearer now?

ahhh ok, that all makes sense now! Thank you so much for all your time and explanations :wink:

We’re all here to learn, and to help eachother :wink:

I hope it helps you master lua, and that we’ll see alot of inputs of you later, and we that the codea community has won an extra active member… :wink:

@stevon8ter math.pi is not a function, it’s a constant…

@SkyTheCoder i didn’t know that, sorry

hides emberassed

But well, I couldn’t think of a function, so i thought math.pi might do the trick, but i was wrong, tho the return function’s still explained to him, and he gets it, i hope hahaha xd
sorry for all other misstakes i make/made/will make

@stevon8er, could you please watch your language