Forum Archive

If statement syntax error

OkieWolf
def button3_tapped(sender):
    sidea = float(v['textfield3'].text)I
    sideb = float(v['textfield4'].text)
    sidec = float(v['textfield5'].text)
    if sidea is not None and sideb is not None
        sidec = sidea + sideb
        v['label1'].text = 'sidec = ' + str(sidec)

I have a dialog box with three text fields and a button. Upon pushing the button I want to look at the three fields and see if they’re blank. If two are not then do something. I keep getting a syntax error on the above if statement and can’t figure out why.
I also tried if (sidea.length()!=0)

mcriley821

@OkieWolf
try to format your code with the button, but from what I can tell, it looks like you’re missing a colon ':' after the conditions of the if statement

Like so

if sidea and sideb:#colon right here
    #do stuff
stephen

@OkieWolf said:

def button3_tapped(sender):
sidea = float(v['textfield3'].text)I
sideb = float(v['textfield4'].text)
sidec = float(v['textfield5'].text)
if sidea is not None and sideb is not None
sidec = sidea + sideb
v['label1'].text = 'sidec = ' + str(sidec)

def button3_tapped(sender):
    sidea = float(v['textfield3'].text)I # <= remove "I" typo
    sideb = float(v['textfield4'].text)
    sidec = float(v['textfield5'].text)

    # checking if not None 
    if sidea and sideb: # <= you forgot your ":" statment closing
        sidec = sidea + sideb
        v['label1'].text = f'sidec = {sidec}' # changed to fstring 

Also remember to use code format on posts 😀 thnk you!

```

OkieWolf

The below works. But the if statement isn’t catching the blank textfield. If one is blank it errors trying to create sidea or sideb (whichever is blank). Also, it never gets to the else statement.

`` def button3_tapped(sender): if (v['textfield3'].text) is not None and (v['textfield4'].text) is not None: sidea = float(v['textfield3'].text) sideb = float(v['textfield4'].text) sidec = sidea + sideb v['textfield5'].text = 'sidec = ' + str(sidec) else: v['textfield5'].text = 'ENTER ALL REQUIRED FIELDS'

mcriley821

@OkieWolf

def button3_tapped(sender):
    if v['textfield3'].text and v['textfield4'].text:
        try:
                sidea = float(v['textfield3'].text)
                sideb = float(v['textfield4'].text)
        except ValueError:
                v['textfield5'].text = 'ENTER ALL REQUIRED FIELDS CORRECTLY'
        else:
                sidec = sidea + sideb
                v['textfield5'].text = f'sidec = {sidec}'
OkieWolf

Figured it out. See below....

def button3_tapped(sender): if (v['textfield3'].text)!="" and (v['textfield4'].text)!="": sidea = float(v['textfield3'].text) sideb = float(v['textfield4'].text) sidec = sidea + sideb v['textfield5'].text = 'sidec = ' + str(sidec) else: v['textfield5'].text = 'ENTER ALL REQUIRED FIELDS'

mcriley821

@OkieWolf this will throw an exception if the string can’t convert to a float. If you suspect that won’t happen, your code is fine. Otherwise my previous code would be more robust

OkieWolf

New issue.
I want to change the background color of the textfield to red if one of the fields is blank. Below is what I’ve done. It doesn’t error but it doesn’t change the color either. I also tried ‘red’ instead of the hex code but that doesn’t work either.

def button3_tapped(sender): if (v['textfield3'].text)!="" and (v['textfield4'].text)!="": sidea = float(v['textfield3'].text) sideb = float(v['textfield4'].text) sidec = sidea + sideb v['textfield5'].text = 'sidec = ' + str(sidec) else: v['textfield5'].background_color = 'fffffff8' v['textfield5'].text = 'ENTER ALL FIELDS'

mcriley821

@OkieWolf
To specify hex you have to have a # in front

red = '#ff0000'

The current hex value you have is mostly white. It’s also too long. 'red' should work too

OkieWolf

@mcriley821
Still doesn’t change

mcriley821

@OkieWolf then it’s not making it to the else statement. What are you inputting to the textfields? Maybe one of them is white space?

OkieWolf

@mcriley821
It’s getting to the else statement because it’s inputting the text “Enter All Fields”. It just won’t change the color.

mcriley821

@OkieWolf

Scratch that, sorry. I was thinking of a label. A textField doesn’t really have a background. It’s background is behind the white layer. What you could do instead is make a red border.

If you really want the whole thing red, I can write a small bit of code with objc_util

cvp

@OkieWolf already done here

mikael

@OkieWolf, you hit one of known quirks. You can set bordered to False, after which background_color works. Or if that appearance does not work for you, @cvp’s solution can be turned into a helper function that you can call with just 'red':

def textfield_background(tf, color):
    import objc_util
    tfo = tf.objc_instance.textField()
    tfo.backgroundColor = objc_util.UIColor.colorWithRed_green_blue_alpha_(
        *ui.parse_color(color))
OkieWolf

What about text color? Can I change the textfield text color to red?

cvp

@OkieWolf .text_color = 'red'

OkieWolf

@mikael
How do I set bordered to false?

OkieWolf

Here’s the completed button using the Pythagorean Theorem to calculate. It looks to see which of the three textfields is blank then calculates what it should be based on the input of the other two.

def button3_tapped(sender): if (v['textfield3'].text)!="" and (v['textfield4'].text)!="": hyp = float(v['textfield3'].text) sht = float(v['textfield4'].text) hyp = pow(hyp,2) sht = pow(sht,2) lng = math.sqrt(hyp - sht) v['textfield5'].text_color = 'green' v['textfield5'].text = str(lng) elif (v['textfield4'].text)!="" and (v['textfield5'].text)!="": sht = float(v['textfield4'].text) lng = float(v['textfield5'].text) sht = pow(sht,2) lng = pow(lng,2) hyp = math.sqrt(sht + lng) v['textfield3'].text_color = 'green' v['textfield3'].text = str(hyp) elif (v['textfield3'].text)!="" and (v['textfield5'].text)!="": hyp = float(v['textfield3'].text) lng = float(v['textfield5'].text) hyp = pow(hyp,2) lng = pow(lng,2) sht = math.sqrt(hyp - lng) v['textfield4'].text_color = 'green' v['textfield4'].text = str(sht) else: v['textfield5'].text_color = 'red' v['textfield5'].text = 'ENTER ALL FIELDS'

ccc

The logic is easier to follow if field names describe their content.

def button3_tapped(sender):
    hypotenuse = float(v['hypotenuse'].text or 0)
    short = float(v['short'].text or 0)
    long = float(v['long'].text or 0)
    if len([x for x in (hypotenuse, short, long) if x]) != 2:
        v['long'].text = "Enter floats in 2 fields"
        v['long'].text_color = 'red'
        return
    if hypotenuse:
        if short and not long:
            v['long'].text = str(math.sqrt(hypotenuse ** 2 - short ** 2))
            v['long'].text_color = 'green'
        elif long and not short:
            v['short'].txt = str(math.sqrt(hypotenuse ** 2 - long ** 2))
            v['short'].text_color = 'green'
    else:
        v['hypotenuse'].text = str(math.sqrt(short ** 2 + long ** 2))
        v['hypotenuse'].text_color = 'green'
OkieWolf

@ccc
Could you please explain how this works in more detail?
I realize you’ve renamed textfields but I’m not exactly understanding how the code is working. I’m mainly not understanding what’s happening with the or 0 and then the if len([x for x in (hypotenuse, short, long) if x]) != 2

hypotenuse = float(v['hypotenuse'].text or 0) short = float(v['short'].text or 0) long = float(v['long'].text or 0) if len([x for x in (hypotenuse, short, long) if x]) != 2:

mcriley821

@OkieWolf

hypotenuse = float(v['hypotenuse'].text or 0) short = float(v['short'].text or 0) long = float(v['long'].text or 0) if len([x for x in (hypotenuse, short, long) if x]) != 2:

v['short'].text or 0 will choose 0 if the text is "". You won’t hit an exception for a blank textfield. You will get an error if the text is alphabetical though.

(hypotenuse,short,long) is a tuple and [x for x in (hypotenuse,short,long) if x] is a list comprehension that steps through the tuple
and makes a list of the values that exist. Then if the length of that list isn’t 2, then you don’t have a correct input

OkieWolf

I need to probably rewrite the whole program because I’ve added more error trapping and a fourth textfield. It has increased complexity quite a bit, at least for me. It now cycles through all four textfields, find any two valid fields, decides whether to use Pythagorean Theorem or plain trig, and checks all for errors. One error in particular is that it is possible with the answers to have the short side of the triangle be longer than the long side. Obviously this can never happen so it’s now trapped and alerts the user.
Below is what I now have. I realize my code is a longer than it needs to be and fairly cumbersome at this point but I’m just learning Python and intend to try to rewrite it in a better and more efficient way.

def button3_tapped(sender): if (v['textfield3'].text)!="" and (v['textfield4'].text)!="": v['label7'].background_color = 'white' v['label7'].text_color = 'white' v['label7'].text = '' hyp = float(v['textfield3'].text) sht = float(v['textfield4'].text) hypa = hyp shta = sht hyp = pow(hyp,2) sht = pow(sht,2) lng = math.sqrt(hyp - sht) lnga = lng ang = math.asin(shta/hypa) ang = math.degrees(ang) v['textfield5'].text_color = 'green' v['textfield5'].text = str(lng) v['textfield6'].text_color = 'green' v['textfield6'].text = str(ang) shtb = float(v['textfield4'].text) lngb = float(v['textfield5'].text) if shtb > lngb: v['label7'].background_color = 'red' v['label7'].text_color = 'white' v['label7'].text = 'ERROR. Short side cannot be longer than long side.' elif (v['textfield4'].text)!="" and (v['textfield5'].text)!="": v['label7'].background_color = 'white' v['label7'].text_color = 'white' v['label7'].text = '' sht = float(v['textfield4'].text) shta = sht lng = float(v['textfield5'].text) lnga = lng sht = pow(sht,2) lng = pow(lng,2) hyp = math.sqrt(sht + lng) hypa = hyp ang = math.asin(shta/hypa) ang = math.degrees(ang) v['textfield3'].text_color = 'green' v['textfield3'].text = str(hyp) v['textfield6'].text_color = 'green' v['textfield6'].text = str(ang) shtb = float(v['textfield4'].text) lngb = float(v['textfield5'].text) if shtb > lngb: v['label7'].background_color = 'red' v['label7'].text_color = 'white' v['label7'].text = 'ERROR. Short side cannot be longer than long side.' elif (v['textfield3'].text)!="" and (v['textfield5'].text)!="": v['label7'].background_color = 'white' v['label7'].text_color = 'white' v['label7'].text = '' hyp = float(v['textfield3'].text) hypa = hyp lng = float(v['textfield5'].text) lnga = lng hyp = pow(hyp,2) lng = pow(lng,2) sht = math.sqrt(hyp - lng) shta = sht ang = math.asin(shta/hypa) ang = math.degrees(ang) v['textfield4'].text_color = 'green' v['textfield4'].text = str(sht) v['textfield6'].text_color = 'green' v['textfield6'].text = str(ang) shtb = float(v['textfield4'].text) lngb = float(v['textfield5'].text) if shtb > lngb: v['label7'].background_color = 'red' v['label7'].text_color = 'white' v['label7'].text = 'ERROR. Short side cannot be longer than long side.' elif (v['textfield3'].text)!="" and (v['textfield6'].text)!="": v['label7'].background_color = 'white' v['label7'].text_color = 'white' v['label7'].text = '' hyp = float(v['textfield3'].text) ang = float(v['textfield6'].text) ang = math.radians(ang) hypa = hyp sht = hyp * math.sin(ang) shta = sht hypc = pow(hyp,2) shtc = pow(sht,2) lng = math.sqrt(hypc - shtc) lnga = lng v['textfield5'].text_color = 'green' v['textfield5'].text = str(lng) v['textfield4'].text_color = 'green' v['textfield4'].text = str(sht) shtb = float(v['textfield4'].text) lngb = float(v['textfield5'].text) if shtb > lngb: v['label7'].background_color = 'red' v['label7'].text_color = 'white' v['label7'].text = 'ERROR. Short side cannot be longer than long side.' elif (v['textfield4'].text)!="" and (v['textfield6'].text)!="": v['label7'].background_color = 'white' v['label7'].text_color = 'white' v['label7'].text = '' sht = float(v['textfield4'].text) ang = float(v['textfield6'].text) ang = math.radians(ang) shta = sht hyp = sht / math.sin(ang) hypa = hyp hypc = pow(hyp,2) shtc = pow(sht,2) lng = math.sqrt(hypc - shtc) shta = sht v['textfield5'].text_color = 'green' v['textfield5'].text = str(lng) v['textfield3'].text_color = 'green' v['textfield3'].text = str(hyp) shtb = float(v['textfield4'].text) lngb = float(v['textfield5'].text) if shtb > lngb: v['label7'].background_color = 'red' v['label7'].text_color = 'white' v['label7'].text = 'ERROR. Short side cannot be longer than long side.' elif (v['textfield5'].text)!="" and (v['textfield6'].text)!="": v['label7'].background_color = 'white' v['label7'].text_color = 'white' v['label7'].text = '' lng = float(v['textfield5'].text) ang = float(v['textfield6'].text) ang = math.radians(ang) lnga = lng hyp = lng / math.cos(ang) hypa = hyp hypc = pow(hyp,2) lngc = pow(lng,2) sht = math.sqrt(hypc - lngc) shta = sht v['textfield4'].text_color = 'green' v['textfield4'].text = str(sht) v['textfield3'].text_color = 'green' v['textfield3'].text = str(hyp) shtb = float(v['textfield4'].text) lngb = float(v['textfield5'].text) if shtb > lngb: v['label7'].background_color = 'red' v['label7'].text_color = 'white' v['label7'].text = 'ERROR. Short side cannot be longer than long side.' else: v['label7'].background_color = 'red' v['label7'].text_color = 'white' v['label7'].text = 'ERROR'

OkieWolf

If you import math why do you still have to say math.sqrt and math.cos?
But then other things like pow don’t have to say math.pow.

ccc

pow() is a Python builtin. https://docs.python.org/3/library/functions.html

You can also say from math import cos, sin, tan to use the single word functions.

OkieWolf

I’m attempting to rewrite to make more efficient. I’m trying to utilize some of the code snippets you guys have given. However, the code below only works if hypotenuse and short are filled out. Or am I missing something?

def button3_tapped(sender): hypotenuse = float(v['hypotenuse'].text or 0) short = float(v['short'].text or 0) long = float(v['long'].text or 0) if len([x for x in (hypotenuse, short, long) if x]) != 2: v['mess'].text = "Enter two fields" v['mess'].text_color = 'red' return if hypotenuse: if short and not long: v['long'].text = str(math.sqrt(hypotenuse ** 2 - short ** 2)) v['long'].text_color = 'green' elif long and not short: v['short'].txt = str(math.sqrt(hypotenuse ** 2 - long ** 2)) v['short'].text_color = 'green' else: v['hypotenuse'].text = str(math.sqrt(short ** 2 + long ** 2)) v['hypotenuse'].text_color = 'green'

OkieWolf

@ccc

I’m attempting to rewrite my code to be more efficient and am utilizing a couple of code snippets that a couple of you have supplied. However, in the below code I noticed that the output is 0.0 if both inputs happen to be the same number. I’m not understanding why.

def button3_tapped(sender): hypotenuse = float(v['hypotenuse'].text or 0) short = float(v['short'].text or 0) long = float(v['long'].text or 0) if len([x for x in (hypotenuse, short, long) if x]) != 2: v['mess'].text = "Enter two fields" v['mess'].background_color = 'red' v['mess'].text_color = 'white' return if hypotenuse: if short and not long: v['long'].text = str(math.sqrt(hypotenuse ** 2 - short ** 2)) v['long'].text_color = 'green' elif long and not short: v['short'].text = str(math.sqrt(hypotenuse ** 2 - long ** 2)) v['short'].text_color = 'green' else: v['hypotenuse'].text = str(math.sqrt(short ** 2 + long ** 2)) v['hypotenuse'].text_color = 'green'

ccc

if both inputs happen to be the same number

if hypotenuse:
    if short:
        The rules of math say that the hypotenuse must be greater than short.
    else
        The rules of math say that the hypotenuse must be greater than long.
else:
    short could be the same number as long  # <-- this is the only instance where both inputs could be the same number
if hypotenuse and (short >= hypotenuse or long >= hypotenuse):
    raise ValueError("Not allowed by the rules of math.")
OkieWolf

Agreed. It works fine if short and long are the same number, which equals 45 degrees.

OkieWolf

Here’s what I came up with. It’s much shorter and easier to understand and I GREATLY appreciate all the help and patience.
This version does all the other one did plus more. This version will calculate the other side and angle based on two sides input and can now calculate any side of the triangle based on angle and any one of the three sides.

def button3_tapped(sender):
    hypotenuse = float(v['hypotenuse'].text or 0)
    short = float(v['short'].text or 0)
    long = float(v['long'].text or 0)
    angle = float(v['angle'].text or 0)
    if len([x for x in (hypotenuse, short, long, angle) if x]) != 2:
        v['mess'].text = "Enter two fields"
        v['mess'].background_color = 'red'
        v['mess'].text_color = 'white'
        return
    if hypotenuse and not angle:
        if short and not long:
            v['long'].text = str(math.sqrt(hypotenuse ** 2 - short ** 2))
            v['long'].text_color = 'green'
            v['angle'].text = str(math.degrees(math.asin(short / hypotenuse)))
            v['angle'].text_color = 'green'
        elif long and not short:
            v['short'].text = str(math.sqrt(hypotenuse ** 2 - long ** 2))
            v['short'].text_color = 'green'
            v['angle'].text = str(math.degrees(math.acos(long / hypotenuse)))
            v['angle'].text_color = 'green'
    else:
        if not angle:
            v['hypotenuse'].text = str(math.sqrt(short ** 2 + long ** 2))
            v['hypotenuse'].text_color = 'green'
            v['angle'].text = str(math.degrees(math.atan(short / long)))
            v['angle'].text_color = 'green'

    if angle:
        angle = math.radians(angle)
        if short and not long and not hypotenuse:
            v['hypotenuse'].text = str(short / (math.sin(angle)))
            v['hypotenuse'].text_color = 'green'
            v['long'].text = str(short / (math.tan(angle)))
            v['long'].text_color = 'green'
        elif long and not short and not hypotenuse:
            v['hypotenuse'].text = str(long / (math.cos(angle)))
            v['hypotenuse'].text_color = 'green'
            v['short'].text = str(long * (math.tan(angle)))
            v['short'].text_color = 'green'
        elif angle and hypotenuse and not long and not short:
            v['short'].text = str(hypotenuse * (math.sin(angle)))
            v['short'].text_color = 'green'
            v['long'].text = str(hypotenuse * (math.cos(angle)))
            v['long'].text_color = 'green' 
ccc

Please put the trailing three backticks on a line all by themselves.

OkieWolf

@ccc
Done

ccc

OK. Now it is time to separate the business logic from the UI representation. We would need to put all the math logic in a function of the form:

def triangle(a, b, hypotenuse=0, angle=45):
    pass  # math logic goes here

Where triangle(3, 4) returns (3, 4, 5.0, 45)
Where triangle(3, 0) would raise ValueError()

JonB

It seems to me you could also dispense with most of the long / short specific logic, and just compute the other edge, then figure out which one is the long vs short after the fact.

OkieWolf

@ccc

Please explain

def triangle(a, b, hypotenuse=0, angle=45):
    pass  # math logic goes here
Where triangle(3, 4) returns (3, 4, 5.0, 45)
Where triangle(3, 0) would raise ValueError() 
ccc

This was an invitation for you or someone else to write a function that can take between 2 and 4 parameters and calculate all other variables or raise an exception if there is no possible solution. This function would allow us to isolate all UI operations from all math operations. It would make it easier to test our math operations without the UI and would allow us to easily port the math operations to a different platform.

OkieWolf

@ccc

Below will calculate short and long with given hypotenuse and angle but you have to enter zero for short and long input.

```
import math

def triangle(short, long, hypotenuse, angle):
pass
if hypotenuse and angle:
angle = math.radians(angle)
print ('Short = ' + str(hypotenuse * (math.sin(angle))))
print ('Long = ' + str(hypotenuse * (math.cos(angle))))

triangle(0,0,10,30)
```

OkieWolf

@ccc

This will calculate any side or angle. But input still has to be zero for unknowns at input.

import math

def triangle(short, long, hypotenuse, angle):
    pass
    if len([x for x in (hypotenuse, short, long, angle) if x]) == 2:
        if hypotenuse and angle:
            angle = math.radians(angle)
            print   ('Short = ' + str(hypotenuse * (math.sin(angle))))
            print   ('Long = ' + str(hypotenuse * (math.cos(angle))))
        elif long and angle:
            angle = math.radians(angle)
            print   ('Short = ' + str(long * (math.tan(angle))))
            print   ('Hypotnuse = ' + str(long / (math.cos(angle))))
        elif short and angle:
            angle = math.radians(angle)
            print   ('Long = ' + str(short / (math.tan(angle))))
            print   ('Hypotnuse = ' + str(short / (math.sin(angle))))
        elif hypotenuse and short:
            print ('Long = ' + str(math.sqrt(hypotenuse ** 2 - short ** 2)))
            print ('Angle = ' + str(math.degrees(math.asin(short / hypotenuse))))
        elif hypotenuse and long:
            print ('Short = ' + str(math.sqrt(hypotenuse ** 2 - long ** 2)))
            print ('Angle = ' + str(math.degrees(math.acos(long / hypotenuse))))
        elif short and long:
            print ('Hypotenuse = ' + str(math.sqrt(short ** 2 + long ** 2)))
            print ('Angle = ' + str(math.degrees(math.atan(short / long))))
    else:
        print ("ERROR")

triangle(5,0,10,0) 
ccc

Step 0: drop the pass line.
Step 1:

    if len([x for x in (hypotenuse, short, long, angle) if x]) != 2:
        raise ValueError("Exactly two parameters must be zero.")

Step 2: change triangle() so it never prints but instead returns the answer with the statement return short, long, hypotenuse, angle
Step 3: change triangle(5,0,10,0) to print(triangle(5,0,10,0)).

Step 1: is called a fast-fail which is safer and more readable than failing later in the function. Basically is says "I see a bad situation (bad input data) so I am going to raise an exception and stop processing".

mikael

@ccc, I am sure I just saw you using count somewhere:

if (hyp, ...).count(0) != 2:
    raise ...
OkieWolf

@ccc

I don’t understand step 2

Step 2: change triangle() so it never prints but instead returns the answer with the statement return short, long, hypotenuse, angle.

Are you wanting me to change....
def triangle(short, long, hypotenuse, angle):

Also, changing to print(triangle(5,0,10,0)) adds “none” after returned values

ccc
def triangle(short, long, hypotenuse, angle):
    # Your code goes here...
    # Your code contains no print() calls.
    return short, long, hypotenuse, angle
cvp

Your code contains no print() calls, like

        if hypotenuse and angle:
            angle = math.radians(angle)
            short = hypotenuse * math.sin(angle)
            long  = hypotenuse * math.cos(angle) 
OkieWolf

@cvp

I still don’t know what you’re wanting. My code has many print calls.
Adding return short, long, hypotenuse, angle where you have it above won’t do anything because it’s part of the last elif. If I add it in line with def Tringle it errors.

import math

def triangle(short, long, hypotenuse, angle):
    pass
    if len([x for x in (hypotenuse, short, long, angle) if x]) == 2:
        if hypotenuse and angle:
            angle = math.radians(angle)
            print   ('Short = ' + str(hypotenuse * (math.sin(angle))))
            print   ('Long = ' + str(hypotenuse * (math.cos(angle))))
        elif long and angle:
            angle = math.radians(angle)
            print   ('Short = ' + str(long * (math.tan(angle))))
            print   ('Hypotnuse = ' + str(long / (math.cos(angle))))
        elif short and angle:
            angle = math.radians(angle)
            print   ('Long = ' + str(short / (math.tan(angle))))
            print   ('Hypotnuse = ' + str(short / (math.sin(angle))))
        elif hypotenuse and short:
            print ('Long = ' + str(math.sqrt(hypotenuse ** 2 - short ** 2)))
            print ('Angle = ' + str(math.degrees(math.asin(short / hypotenuse))))
        elif hypotenuse and long:
            print ('Short = ' + str(math.sqrt(hypotenuse ** 2 - long ** 2)))
            print ('Angle = ' + str(math.degrees(math.acos(long / hypotenuse))))
        elif short and long:
            print ('Hypotenuse = ' + str(math.sqrt(short ** 2 + long ** 2)))
            print ('Angle = ' + str(math.degrees(math.atan(short / long))))
    else:
        print ("ERROR")

triangle(5,0,10,0)  
cvp

@OkieWolf I understand, I only want to show what @ccc adviced. The triangle code without any print and only one print of triangle results

OkieWolf

@cvp

I think I understand now. But I can’t get the indentation at “return” to stop erroring.

import math

def triangle(short, long, hypotenuse, angle):
    if len([x for x in (hypotenuse, short, long, angle) if x]) != 2:
        raise ValueError("Exactly two parameters must be zero.")
    if hypotenuse and angle:
        angle = math.radians(angle)
        print   ('Short = ' + str(hypotenuse * (math.sin(angle))))
        print   ('Long = ' + str(hypotenuse * (math.cos(angle))))
    elif long and angle:
        angle = math.radians(angle)
        print   ('Short = ' + str(long * (math.tan(angle))))
        print   ('Hypotnuse = ' + str(long / (math.cos(angle))))
    elif short and angle:
        angle = math.radians(angle)
        print   ('Long = ' + str(short / (math.tan(angle))))
        print   ('Hypotnuse = ' + str(short / (math.sin(angle))))
    elif hypotenuse and short:
        print ('Long = ' + str(math.sqrt(hypotenuse ** 2 - short ** 2)))
        print ('Angle = ' + str(math.degrees(math.asin(short / hypotenuse))))
    elif hypotenuse and long:
        print ('Short = ' + str(math.sqrt(hypotenuse ** 2 - long ** 2)))
        print ('Angle = ' + str(math.degrees(math.acos(long / hypotenuse))))
    elif short and long:
        print ('Hypotenuse = ' + str(math.sqrt(short ** 2 + long ** 2)))
        print ('Angle = ' + str(math.degrees(math.atan(short / long))))
  return(short, long, hypotenuse, angle)

#triangle(5,0,10,0) 
ccc
from math import acos, asin, atan, cos, degrees, radians, sin, sqrt, tan


def triangle(short, long, hypotenuse=0, angle=0):
    if (hypotenuse, short, long, angle).count(0) != 2:
        raise ValueError("Exactly two parameters must be zero.")
    radians_angle = radians(angle)
    if short:
        if long:
            hypotenuse = sqrt(short ** 2 + long ** 2)
            angle = degrees(atan(short / long))
        elif hypotenuse:
            long = sqrt(hypotenuse ** 2 - short ** 2)
            angle = degrees(asin(short / hypotenuse))
        else:  # short and angle
            long = short / tan(radians_angle)
            hypotenuse = short / sin(radians_angle)
    elif long:
        if hypotenuse:
            short = sqrt(hypotenuse ** 2 - long ** 2)
            angle = degrees(acos(long / hypotenuse))
        else:  # long and angle
            short = long * tan(radians_angle)
            hypotenuse = long / cos(radians_angle)
    else:  # hypotenuse and angle
        short = hypotenuse * sin(radians_angle)
        long = hypotenuse * cos(radians_angle)
    short, long, hypotenuse = sorted([short, long, hypotenuse])
    return float(short), float(long), float(hypotenuse), float(angle)


# The result for each of these should be (3.0, 4.0, 5.0, 36.8698976458440x)
print(triangle(3, 4))  # short and long
print(triangle(3, 0, 5))  # short and hypotenuse
print(triangle(0, 4, 5))  # long and hypotenuse
print(triangle(0, 0, 5, 36.86989764584402))  # hypotenuse and angle
ccc

Can one of you help me to correct the math is the function above?

# The result for each of these SHOULD be (3.0, 4.0, 5.0, 45.0)
print(triangle(3, 4))  # short and long
print(triangle(3, 0, 5))  # short and hypotenuse
print(triangle(0, 4, 5))  # long and hypotenuse
print(triangle(0, 0, 5, 45))  # hypotenuse and angle
cvp

@ccc as short and long are différent, why do you think angle could be 45°?

cvp

@ccc error, you use angle instead of radians_angle

    else:  # hypotenuse and angle
        short = hypotenuse * sin(radians_angle)
        long = hypotenuse * cos(radians_angle) 
ccc

Thanks! Now you know why I failed trig back in the day...

Both issues fixed in the code above.

ccc

For completeness...

def button3_tapped(sender):
    hypotenuse = float(v['hypotenuse'].text or 0)
    short = float(v['short'].text or 0)
    long = float(v['long'].text or 0)
    angle = float(v['angle'].text or 0)
    try:
        short, long, hypotenuse, angle = triangle(short, long, hypotenuse, angle)
    except ValueError:
        v['mess'].text = "Enter two fields"
        v['mess'].background_color = 'red'
        v['mess'].text_color = 'white'
        return
    v['short'].text = str(short)
    v['long'].text = str(long)
    v['hypotenuse'].text = str(hypotenuse)
    v['angle'].text = str(angle)
cvp

@ccc said:

For completeness..

def button3_tapped(sender):
    # erase previous eventual error message
    v['mess'].text = ""
    v['mess'].background_color = 'white'
    .
    .
    .