How to do some math?

I have two questions. Code below is reconstructed from memory, i don’t have my ipad with me, so it might be wrongly coded… oh well.

the first example is supposed to be a sine calculator (basically math.sin). I can’t get it to increase accuracy beyond a certain number of digits. I don’t need that accuracy now (and probably never), but I wanted to be able to do it


local function factorial(n)
    assert( n > 1 )
    local v = 1
    for x= 2, n do
        v = v * x    
    end
    return v
end

function mySine(number)
    local power = 3            -- n^3/3!, n^5/5!, ...  
    local result = number
    for x = 1, 10 do
        if x % 2 == 1 then     -- subtract
            result = result - number ^ power/factorial(power)
        else
            result = result + number ^ power/factorial(power)
        end
        power = power + 2
    end
    return result
end

Second question

I have a ship class. So it’s a really simple Asteroids style ship. I tried using the Law of Sines to calculate the sides, but it didn’t work right (so Law of sines is side a/sine(A) = side b/sine(B) = side c/sine(C) ) (i got what I felt was the wrong values when I inputted a known angle to a known side)

Umm, that wasn’t the question. The question is:

Where is the y position on this triangle of point c

point a is at 0,0
point b is at 24,0
point c is at 12, ?
angle a is 70*
angle b is 70*
angle c is 40*

local y 
-- y should be calculated from the angles of the triangle. 
-- 
mesh = mesh()
mesh.vertices = {vec2(0,0), vec2(24,0), vec2(12, y)}

-- angle at 0,0 is 70*
-- angle at 24,0 is also 70*
-- angle at the third point should be 40*

As for your first question, the number that is being added and subtracted to the result is getting small really fast. After a few calculations, the value is too small for Codea’s 64 bit math so basically you’re just adding and subtracting almost 0. So no matter how many times you try, the result isn’t changing.

As for you second question, the law of sines will give you the length of the side opposite the angle. It won’t give you the coordinates of the corners. You need to do other calculations to get the corner coordinates.

You need tan to work out that coordinate: y = 12 math.tan(math.rad(70)).

@xThomas Here’s another version of the sine series. This is about the best resolution you can do before the math used by Codea breaks down. This is 9 iterations in the sine function.

function setup()
    ang=2
    print("math.sin ",math.sin(ang))
    print("calc sin ",sine(ang))
end

function sine(nbr)
    s=nbr
    v=-1
    for a=3,19,2 do
        s=s+(nbr^a)/(fac(a)*v) 
        v=v*-1  
    end
    return s
end

function fac(nbr)
    n=1
    for z=2,nbr do
        n=z*n
    end
    return n
end

@xThomas Here’s something I found fun writing. You can vary the x,y values and angles of points 1 and 2 and calculate the x,y values and angle of point 3.

supportedOrientations(LANDSCAPE_ANY)

function setup()
    print("Slide the print window down to show the angles.")
    textMode(CORNER)
    p1x,p1y,p2x,p2y,a1,a2=0,0,0,0,0,0
    parameter.integer("p1x",0,300,100,calc)
    parameter.integer("p1y",20,500,100,calc)
    parameter.integer("p2x",20,600,400,calc)
    parameter.integer("p2y",20,700,100,calc)
    parameter.integer("a1",0,90,60,calc)
    parameter.integer("a2",0,90,60,calc)
end

function calc()
    calcP3(vec2(p1x,p1y),vec2(p2x,p2y),a1,a2)
end

function calcP3(p1,p2,ang1,ang2)    -- calculate x,y values for point 3
    ang3=180-(ang1+ang2)
    d=p2-p1
    t3=math.sqrt(d.x^2+d.y^2)
    t2=t3*math.sin(math.rad(ang2))/math.sin(math.rad(ang3))
    s1=p1.x*d.x+p1.y*d.y+t2*t3*math.cos(math.rad(ang1))
    s2=p2.y*d.x-p2.x*d.y+t2*t3*math.sin(math.rad(ang1))
    p3x=(1/t3^2)*(d.x*s1-d.y*s2)
    p3y=(1/t3^2)*(d.y*s1+d.x*s2)
end

function draw()
    background(40, 40, 50)
    stroke(255, 0, 0, 255)
    fill(255, 0, 0, 255)
    ellipse(p1x,p1y,10)
    ellipse(p2x,p2y,10)
    ellipse(p3x,p3y,10)  
    stroke(255)
    strokeWidth(2)
    line(p1x,p1y,p2x,p2y)  
    line(p2x,p2y,p3x,p3y)  
    line(p3x,p3y,p1x,p1y) 
    fill(0, 255, 0, 255)
    text("  P1 ("..p1x.." , "..p1y..")  "..a1,p1x-80,p1y-25) 
    text("  P2 ("..p2x.." , "..p2y..")  "..a2,p2x-80,p2y-25) 
    text("  P3 ("..(p3x//1).." , "..(p3y//1)..")  "..ang3,p3x-80,p3y+10) 
end

@dave1707 I’m still hoping that one day you’ll see the benefit of vectors …

-- AnglesAndVectors

supportedOrientations(LANDSCAPE_ANY)

function setup()
    print("Slide the print window down to show the angles.")
    textMode(CORNER)
    p1 = vec2(0,0)
    p2 = vec2(0,0)
    a1 = 0
    a2 = 0
    parameter.integer("p1x",0,300,100,function(x) p1.x = x end)
    parameter.integer("p1y",20,500,100,function(y) p1.y = y end)
    parameter.integer("p2x",20,600,400,function(x) p2.x = x end)
    parameter.integer("p2y",20,700,100,function(y) p2.y = y end)
    parameter.integer("a1",0,90,60)
    parameter.integer("a2",0,90,60)
end

function calcP3(p1,p2,ang1,ang2)    -- calculate x,y values for point 3
    local d1=(p2-p1):rotate(math.rad(ang1))
    local n2=(p1-p2):rotate(math.rad(-ang2+90))
    return p1 + (p2-p1):dot(n2)/d1:dot(n2) * d1, 180-(ang1+ang2)
end

function draw()
    background(40, 40, 50)
    stroke(255, 0, 0, 255)
    fill(255, 0, 0, 255)
    local p3,a3 = calcP3(p1,p2,a1,a2)
    ellipse(p1.x,p1.y,10)
    ellipse(p2.x,p2.y,10)
    ellipse(p3.x,p3.y,10)  
    stroke(255)
    strokeWidth(2)
    line(p1.x,p1.y,p2.x,p2.y)  
    line(p2.x,p2.y,p3.x,p3.y)  
    line(p3.x,p3.y,p1.x,p1.y) 
    fill(0, 255, 0, 255)
    text(string.format("P%d (%d,%d) %d",1,p1.x,p1.y,a1),p1.x-80,p1.y-25)
    text(string.format("P%d (%d,%d) %d",2,p2.x,p2.y,a2),p2.x-80,p2.y-25) 
    text(string.format("P%d (%d,%d) %d",3,p3.x//1,p3.y//1,a3),p3.x-80,p3.y+10)
end

Here’s a more efficient version of the sine serie. Rather than work out the factorials afresh for each coefficient, it uses the previous one to work out the next one.

-- SineSeries

function setup()
    local ang=2
    print("math.sin ",math.sin(ang))
    print("calc sin ",sine(ang))
end

function sine(x)
    local t=x
    local s=t
    local a = 3
    while t ~= 0 do
        t = -t * x * x / a / (a-1) 
        s = s + t
        a = a + 2
    end
    print(a)
    return s
end

@LoopSpace I’d like to use vectors, but for some reason I don’t seem to fully understand why they work. I’m used to code where I can look at a line of code and know what it does and why. The vector code seems to do things that I don’t see. For instance, in your version of the function calcP3, none of that code tells me anything. I know what the commands do, but why they work eludes me. Maybe the more you replace my code with vectors, the more I’ll start to understand them.

@LoopSpace Here’s another version eliminating the fac function. I only go to 19 in the for loop because 21 causes a wrong calculations in Codea math.

function setup()
    ang=1
    print("math.sin ",math.sin(ang))
    print("calc sin ",sine(ang))
end

function sine(nbr)
    s=nbr
    f=-6
    for a=3,19,2 do
        s=s+(nbr^a)/f
        f=f*(a+1)*(a+2)*-1
    end
    return s
end

Thank you very much! :slight_smile:

@dave1707 I tried to reply to your post on my profile page, but I don’t think notifications work there, so I’m reposting it here.

In 2D, you can describe a line by picking a vector orthogonal to it, say n, and a point on it, say a, and then the line consists of all points x such that n:dot(x) = n:dot(a). The vector n can be found by taking a vector along the line and rotating it 90 degrees (which is why all the rotates are in the code). This description is very useful for testing a vector to see if it is on the line, but isn’t useful for generating vectors on that line.

Another description, which interchanges the pros and cons of the previous method, uses a point on the line, say b, and a vector along it, say d. Then vectors on the line are of the form b + t * d for any number t.

We can use these descriptions to find the intersection of two lines. Given n and a in the first description for the first line and b and din the second description for the second line, we’re looking for t such that b + t * d is on the first line. That is, we want t such that:

n:dot(b + t * d) = n:dot(a)

Since the dot product is linear, we can rewrite this as:

n:dot(b) + t * n:dot(d) = n:dot(a)

and this rearranges to:

t = (n:dot(a) - n:dot(b))/n:dot(d)

which can be rearranged a little bit more to:

t = n:dot(a - b) / n:dot(d)

Substituting back in, we get that the intersection of two lines is given by:

b + n:dot(a - b)/n:dot(d) * d

which is pretty much what’s in calcP3. Looking again at that code, I see that my dot products are the other way round, but since u:dot(v) = v:dot(u) then that doesn’t matter.

I hope that helps a bit!

@LoopSpace Thanks for the explanation. I dont know what it says, but I’ll have to get out some graph paper and work out what you’re saying line by line. I seem to understand things better if I can see a picture of what’s happening then by reading about what’s happening.