so I am new to python, im using it for a couple classes, I am making programs to run calculations. here I have my code for 3 dimensional vectors, I ran into an issue however when I input a vector with Fx=0 Fy=-6 and Fz=8, it gave me a math domain error when computing the variable s. I tried the math by hand, works fine, had it print all the variables used for s just prior to the error and did the line of math code by hand using the numbers and it checks out, and it works for just about every other 3d vector ive thrown at it, im not sure why it crashes there. also if you have any advice on how to do it better, I am all ears (though I appreciate any links to code or pips to import, I have to write the code itself to be able to use it for class). code below:
#blue triangle
#if else
import math
a=input('what is the altitude angle theta z:')
s=input('what is the swing angle phi:')
F=input('what is the magnitude:')
Fx=input('what is the Fx component:')
Fy=input('what is the Fy component:')
Fz=input('what is the Fz component:')
#Blue triangle functions (Magnitude, Theta z, phi)
if a !='' and s!='' and F!='':
print('---------------------------------------------------------------------------------------')
#a = input('what is the altitude angle theta z:')
#s = input('what is the swing angle phi:')
#F = input('what is the magnitude:')
a=float(a)
s=float(s)
F=float(F)
Sa = math.sin(math.radians(a))
Ca = math.cos(math.radians(a))
Ss = math.sin(math.radians(s))
Cs = math.cos(math.radians(s))
Fx = F*Sa*Cs
Fy = F*Sa*Ss
Fz = F*Ca
print(' Fx=',Fx)
print(' Fy=',Fy)
print(' Fz=',Fz)
print(' Unit vector <',round(Fx/F,4), round(Fy/F,4), round(Fz/F,4), '>')
Fx=''
#Blue triangle functions (Fx,Fy,Fz)
if Fx!='' and Fy!='' and Fz!='':
print('---------------------------------------------------------------------------------------')
Fx=float(Fx)
Fy=float(Fy)
Fz=float(Fz)
F=math.sqrt((Fx**2) (Fy**2) (Fz**2))
a=math.degrees(math.acos(Fz/F))
s=math.degrees(math.asin((Fy/(F*math.sin(math.radians(a))))))
print(' Force=',F)
print(' Altitude of theta z=',a)
print(' planar swing angle phi=',s)
print(' Unit vector <',round(Fx/F,4), round(Fy/F,4), round(Fz/F,4), '>')
print('done')
CodePudding user response:
The error you are getting comes from floating point math being inexact - as documented in the official python docs too
If you break your statement up into a few parts and print the intermediate arguments you can see 1) which command the error is from, and 2) what the input values are for that command.
arg = Fy/(F*math.sin(math.radians(a)))
print(arg)
arg2 = math.asin(arg) # the error is on this line
s = math.degrees(arg2)
Analytically, arg
should be exactly -1 here, but when you print it you will see it has a value of -1.0000000000000002
(see the link above about floating point math being inexact...). Since you cannot take the asin
of a number > 1 or < -1, you get a math domain error. One solution would just be to clip it to a valid range before passing it to the asin
function.
arg = Fy/(F*math.sin(math.radians(a)))
arg_clipped = max([-1, min([1, arg])])
arg2 = math.asin(arg_clipped)
s = math.degrees(arg2)
Most of the time the clipping won't do anything, except for these corner cases where you are at exact right angles and at argument values of exactly 1 or -1.
I would also recommend keeping things in radians through the calculations, and if you need to show the value in degrees just convert it to degrees at the point where you print it.
See also Accurate trig in python and Python cosine function precision.