Cosine rule program

<PLEASE USE THE FOLLOWING TEMPLATE TO HELP YOU CREATE A GREAT POST!>

<Below this line, add a link to the EXACT exercise that you are stuck at.>

<In what way does your code behave incorrectly? Include ALL error messages.>
Traceback (most recent call last):
File “C:\Users\xxxxxx\YYYY\zzzz\xxxx\Testing 543.py”, line 17, in
a_squared = bb+cc-2bc*math.cos(A)
TypeError: unsupported operand type(s) for *: ‘function’ and ‘function’

In addition to the one error i had when I done this before:
", line 17, in
a_squared = b2+c2-2bc*math.cos(A)
TypeError: unsupported operand type(s) for ** or pow(): ‘function’ and ‘int’

<What do you expect to happen instead?>
I am a beginner and I am interested in programming. I am attempting to create a program to work out side a in the mathematics trig cosine rule. I will be using this to help me in my exams. I expect the output to give me a integer but im ending up with the same errors.
I am very new to this program and I just found this website so please help me people. I enjoy doing programming… Anyways, I realised the problem is with the formula as the variables b,c,A are being recognised as variables despite puting int or float. I need help

```python

#This is a simple sample program
import math

def b():
int(input(“What value is side b”)
)
def c():
int(input(“What value is side c”)
)

def A():
int(input(“What value is angle A”)
)

a_squared = bb+cc-2bc*math.cos(A)

print(“The answer to side a squared is” ,a_squared)

<do not remove the three backticks above>

Remove the white space for the end of your int() argument expressions. int() is a function call, so cannot contain line breaks in the argument list.

int(input("What value is side b"))

It wouldn’t hurt if you provided a definition for the Law of Cosines,

Given a triangle with sides, a, b, and c, and angles, A, B, and C where we know the lengths of two sides and the measure of the included angle (S-A-S) we can find the length of the unknown side (the one opposite the known angle) with,

a ** 2 = b ** 2 + c ** 2 - 2 * b * c * math.cos(A)

such that,

a = math.sqrt(b ** 2 + c ** 2 - 2 * b * c * math.cos(A))
1 Like

Ok, I changed it up a bit but now im getting the same error as before:

", line 18, in
a = math.sqrt(b ** 2 + c ** 2 - 2 * b * c * math.cos(A))
TypeError: unsupported operand type(s) for ** or pow(): ‘function’ and ‘int’

Your functions need a return value, and need to be invoked to get at those values.

>>> import math
>>> def side_b():
    return int(input("What value is side b: "))

>>> def side_c():
    return int(input("What value is side c: "))

>>> def angle_A():
    return int(input("What value is angle A: "))

>>> b = side_b()
What value is side b: 11
>>> c = side_c()
What value is side c: 7
>>> A = angle_A()
What value is angle A: 40
>>> a = math.sqrt(b ** 2 + c ** 2 - 2 * b * c * math.cos(A))
>>> a
16.513886928716943
>>> 
1 Like

YAY!! It works thanks for the help mtf, much appreciated! I have created my first program/script which will help me revise. Again, Thanks!

2 Likes

If you have already covered the unit on Object Oriented Programming (introducing classes) then you can get some practice packaging your program in its own environment (an object with its own methods and attributes).

>>> class Shape(object):
    pass

>>> class Triangle(Shape):
    pass

>>> abc = Triangle()
>>> type(abc)
<class '__main__.Triangle'>
>>> 

We know that a triangle has six main attributes, three Sides, and three Angles. Given any three of the six we can find the other three. So our class should have all the attributes, and a basic library of methods, which you are (may I take it) presently in the process of studying (Trigonometry).

Let’s break down the type of problems we will want to be able to solve.

 REF     # KNOWNS
S-A-S    # two sides and one angle
A-S-A    # two angles and one side
S-S-S    # three sides
A-A-A    # just kidding; this has infinite solutions

So our class will have a number of built-in methods, one of which you already have the makings of, solving for the missing side. Some of the solutions we will be after:

S-A-S
  * find missing side
  * find missing angles (with above, refer to S-S-S)

A-S-A
  * find missing angle
  * find missing sides

S-S-S
  * find missing angles

Your teacher may have already taught you to identify a triangle with one of the above types so you know what approach to reach for just by looking at it. It makes sense to have our program organized in the same way.

Math Practice

Given the example from earlier, with b = 11, c = 7 and a computed, we can rewrite the Cosine rule to solve for angles B and C. This is a S-S-S problem.

Assume we have started the program with,

from math import sqrt
from math import cos
from math import sin
from math import acos
from math import asin
from math import radians
from math import degrees

Solving for B we start with,

b = sqrt(a ** 2 + c ** 2 - 2 * a * c * cos(B))

and for C,

c = sqrt(a ** 2 + b ** 2 - 2 * a * b * cos(C))

The unknowns in the above are, cos(B) and cos(C) so we need to isolate them on one side.

b**2 = a**2 + c**2 - 2 * a * c * cos(B) (subtract a**2 and c**2 from both sides)

b**2 - a**2 - c**2 = - 2 * a * c * cos(B) (divide both sides by -2 * a * c)

b**2 - a**2 - c**2
------------------ = cos(B)               (multiply both sides by -1 / -1)
    -2 * a * c

a**2 - b**2 + c**2
------------------ = cos(B)    (take the arccos of the left side to solve for B)
    2 * a * c

            
B = acos((a**2 - b**2 + c**2) / (2 * a * c))

On paper (with the help of a calculator) we can solve this for B. But in Python we have to set the units for the domain to radians. The place to do this would be in the Angle return value.

def angle_A():
    return radians(int(input("What value is angle A? ")))
>>> B = acos((a**2 - b**2 + c**2) / (2 * a * c))
1.7698716291785719
>>> B = degrees(B)
>>> B
101.40617463187526
>>> C = acos((a**2 + b**2 - c**2) / (2 * a * b))
>>> C
0.6735893236134899
>>> 

To understand radians, relate them in terms of circumference;

360 degrees = 2 * pi radians

360 / 2 = 180 degrees = pi radians

To convert from degrees to radians, given angle A,

A degrees * pi radians / 180 degrees = A radians

A radians * 180 degrees / pi radians = A degrees

Here is some sample code (not a class, yet):

from math import sqrt
from math import sin
from math import asin
from math import cos
from math import acos
from math import radians
from math import degrees

def side_b():
    return int(input("What value is side b? "))
def side_c():
    return int(input("What value is side c? "))
def angle_A():
    return radians(int(input("What value is angle A? ")))

b = side_b()
c = side_c()
A = angle_A()

a = sqrt(b ** 2 + c ** 2 - 2 * b * c * cos(A))
B = acos((a**2 - b**2 + c**2) / (2 * a * c))
C = acos((a**2 + b**2 - c**2) / (2 * a * b))

print ((a, b, c))
print ((A, B, C))
print (round(sum([degrees(A), degrees(B), degrees(C)]),1))

Console output

What value is side b? 11
What value is side c? 7
What value is angle A? 40
(7.213123855839256, 11, 7)
(0.6981317007977318, 1.7698716291785719, 0.6735893236134899)
180.0

And so, do I need to ask the values of all the different variables so we can work out what formula to use through some like:

def user_input():
int(input(“What do you want to work out”)
)

Then do I need to use the IF statement and else/elif statements ?

You could ask what type problem it is, S-A-S, A-S-A, or S-S-S which will point you to the variables you need to input.

Ok, good idea. So do I need to use the if statement for example:

def user_input:
input(“What problem is it. Please enter SAS, ASA or SSS?”))

if user_input == SAS:
return int(input(“What is angle A?”))

My point is that it gets a bit messy, so, how can I use the class function as you kindly showed earlier?

Be sure you have completed the unit(s) on classes. Until then, keep everything raw and develop the functions that will eventually become the methods.

Be sure to write that value in quotes, else it looks like a variable.

if user_input == "SAS":

Yesterday I started a post but made some bad errors so put it on hold. I’ve since edited it and brought it back out. Look for it above today’s posts.

Alrighty! So back to where we were about the if statement. By the way, I have read your edit and it seems much more clearer but I need help with re-arranging the different aspects to the script. For example with the

if user_input = “SAS”:
#I dont know what to write here. I need to organise it with the help of Classes as you mentioned. I know you said that I have to complete the whole unit and so I took the time of to go and research about it and I have read about the init, self and class and object variables through the object orientated programming information on the python website. It is very clear, I understand but I still don’t know how to use it in our program. I was thinking maybe along the lines of classing these formulas altogether with sub-categories. I saw how you used the “pass” in the above reply and I was wondering what that does. Thank you!

It is how we can create classes and functions with no code but still make it valid. As we can see, even in that minimal form we can still spawn instances.

I recommend go through the units and complete all the exercises. It’s never a good idea to make a project into a learning experience unless ALL the concepts in use are well understood, already. Do the learning and the practice in chunk size bites. A project usually means biting off way more than we can chew. Ping me when you are ready to proceed.

    print "Okay, looks like a Cosine Rule problem."
    b = side_b()
    c = side_c()
    A = angle_A()
    print ("Givens,\nSide b: %.1f\nSide c: %.1f\nAngle A: %.1f\n" % (b, c, degrees(A)))
    a = sqrt(b ** 2 + c ** 2 - 2 * b * c * cos(A))
    B = acos((a**2 - b**2 + c**2) / (2 * a * c))
    C = acos((a**2 + b**2 - c**2) / (2 * a * b))
    print ("To find,\nSide a: %.1f\nAngle B: %.1f\nAngle C: %.1f\n" % (a, degrees(B), degrees(C)))

Console output

Givens,
Side b: 11.0
Side c: 7.0
Angle A: 40.0

To find,
Side a: 7.2
Angle B: 101.4
Angle C: 38.6

Ok this is what I have so far. Honestly, I do get this exercise. But the little things I keep missing :confused:

from math import sqrt
from math import sin
from math import asin
from math import cos
from math import acos
from math import radians
from math import degrees

def user_input():
    return input("What problem is it? Please enter SAS, ASA or SSS.")

i = user_input()
print(i)



if i == "SAS":
    print(FORMULA_1)
elif i == "ASA":
        print("Did not under stand that")
        
        
    
class FORMULA_1():
    def side_b():
        return int(input("What value is side b? "))
    def side_c():
        return int(input("What value is side c? "))
    def angle_A():
        return radians(int(input("What value is angle A? ")))


b = FORMULA_1.side_b()
c = FORMULA_1.side_c()
A = FORMULA_1.angle_A()

a = sqrt(b ** 2 + c ** 2 - 2 * b * c * cos(A))
B = acos((a**2 - b**2 + c**2) / (2 * a * c))
C = acos((a**2 + b**2 - c**2) / (2 * a * b))

print ((a, b, c))
print ((A, B, C))
print (round(sum([degrees(A), degrees(B), degrees(C)]),1))

Now I need formulas 2 and 3 for ASA and SSS. The script works perfect until here. Can you help me with the formulas?
Thank you!Preformatted text

I left out two other types,

S-S-A    => non-included angle
A-A-S    => non-included side

We have already solved the S-S-S case with the Law of Cosines, given three sides and no known angles.

The above two, as well as A-S-A will use the Law of Sines which we can explore if you have already learned it and have some pencil and paper practice under your belt.

The intended usage would involve instantiating this class. Also, bear in mind that all upper case signifies a GLOBAL CONSTANT to most readers. A class is denoted by a single capital letter… Formula_1

triangle = Formula_1()
b = triangle.side_b()
c = triangle.side_c()
A = triangle.angle_A()

But I think we are still getting ahead of things. Better we hammer out some raw code then optimize and refactor when all the working parts are present. That way it can run from the command line with relative ease.

Let’s consider a full blown version of what we have so far… (imports notwithstanding)

def side_a():
    return int(input("What value is side a? "))

def side_b():
    return int(input("What value is side b? "))

def side_c():
    return int(input("What value is side c? "))
def angle_A():
    return radians(int(input("What value is angle A? ")))

def angle_B():
    return radians(int(input("What value is angle B? ")))

def angle_C():
    return radians(int(input("What value is angle C? ")))
def find_a(A, b, c):
    return sqrt(b ** 2 + c ** 2 - 2 * b * c * cos(A))

def find_b(a, B, c):
    return sqrt(a ** 2 + c ** 2 - 2 * a * c * cos(B))

def find_c(a, b, C):
    return sqrt(a ** 2 + b ** 2 - 2 * a * b * cos(C))
def solve_A(a, b, c):
    return acos((b**2 + c**2 - a**2) / (2 * b * c))

def solve_B(a, b, c):
    return acos((a**2 - b**2 + c**2) / (2 * a * c))

def solve_C(a, b, c):
    return acos((a**2 + b**2 - c**2) / (2 * a * b))
b = side_b()
c = side_c()
A = angle_A()
print ("\nGivens,\nSide b: %.1f\nSide c: %.1f\nAngle A: %.1f\n" % (b, c, degrees(A)))

a = find_a(A, b, c)     # S-A-S
B = solve_B(a, b, c)    # S-S-S
C = solve_C(a, b, c)

print ("To find,\nSide a: %.1f\nAngle B: %.1f\nAngle C: %.1f\n" % (a, degrees(B), degrees(C)))

print (round(sum([degrees(A), degrees(B), degrees(C)]),1))

Slight differences aside, there is a lot of repetition that hints at a more uniform approach. We can feasibly reduce the twelve methods down to four. I’ll leave you to think about this.

Here are two of the four…

def get_side(side):
    return float(input("What value is side %s? " % side))

def get_angle(angle):
    return radians(float(input("What value is angle %s? " % angle)))

b = get_side('b')
c = get_side('c')
A = get_angle('A')

In this version, floats are permitted.

What value is side b? 11
What value is side c? 7
What value is angle A? 40

Givens,
Side b: 11.0
Side c: 7.0
Angle A: 40.0

To find,
Side a: 7.2
Angle B: 101.4
Angle C: 38.6

180.0

The other two will take a bit of thought.

As it were, some thought was all it took.

def solve_SSS(a, b, u):
    return acos((a ** 2 + b ** 2 - u ** 2) / (2 * a * b))

def solve_SAS(a, K, c):
    return sqrt(a ** 2 + c ** 2 - 2 * a * c * cos(K))

a = solve_SAS(b, A, c)
B = solve_SSS(a, c, b)
C = solve_SSS(a, b, c)

Console

What value is side b? 11
What value is side c? 7
What value is angle A? 40

Givens,
Side b: 11.0
Side c: 7.0
Angle A: 40.0

To find,
Side a: 7.2
Angle B: 101.4
Angle C: 38.6

180.0

Usage:

a = solve_SAS(b, A, c)

The known angle is always in the middle.

B = solve_SSS(a, c, b)

The side opposite the unknown angle is always last.

Well, is it not confusing, what if the user has 3 sides? We can’t input a unknown angle. Which is why we must ask them at the start of the script what they want to work out

If you have three sides, you don’t need to know any angles. SSS is how we find all three angles. In the above, ‘unknown angle’ is the one we are seeking to find, A, B, or C. We haven’t written the cases yet to identify all the scenarios.

if user_input = "SSS":
    print ("Okay, looks like a S-S-S problem.")
    a = get_side('a')
    b = get_side('b')
    c = get_side('c')
    print ()
    A = solve_SSS(b, c, a)
    B = solve_SSS(a, c, b)
    C = solve_SSS(a, b, c)
    print ()

Ok this is confusing. So the script looks like this?

from math import sqrt
from math import sin
from math import asin
from math import cos
from math import acos
from math import radians
from math import degrees

def user_input():
    return input("What problem is it? Please enter SAS, ASA or SSS.")

i = user_input()
print(i)

if user_input == "SSS":
    print("Okay, looks like a S-S-S problem.")
    a = get_side('a')
    b = get_side('b')
    c = get_side('c')
    print()
    A = solve_SSS(b, c, a)
    B = solve_SSS(a, c, b)
    C = solve_SSS(a, b, c)
    print()
    
        
        
    
class Formula_1():
    def side_b():
        return int(input("What value is side b? "))
    def side_c():
        return int(input("What value is side c? "))
    def angle_A():
        return radians(int(input("What value is angle A? ")))
triangle = Formula_1()
b = triangle.side_b()
c = triangle.side_c()
A = triangle.angle_A()

a = sqrt(b ** 2 + c ** 2 - 2 * b * c * cos(A))
B = acos((a**2 - b**2 + c**2) / (2 * a * c))
C = acos((a**2 + b**2 - c**2) / (2 * a * b))

print ((a, b, c))
print ((A, B, C))
print (round(sum([degrees(A), degrees(B), degrees(C)]),1))


Getting problem

 b = triangle.side_b()
TypeError: side_b() takes 0 positional arguments but 1 was given

Edit I fixed it. (replaced triangle.side_b() with Formula_1.side_b() )but still confused. Can you please send me you interpretation of the script? Thank you!

I still think it is best right now to keep working on raw methods and set aside the class, for now. You’re compounding the problem. Have you studied the Law of Sines, yet?