Python计算三角形角度时出现math domain error问题求助
问题排查与修复方案
嘿,我帮你找到了触发math domain error的根源,还有几个潜在的代码问题,咱们一步步来解决:
1. 直接报错的核心原因:运算优先级搞错了
你输入angles(11, 20, 30)时,最大边是30(对应变量c),进入了钝角判断的分支。看这段代码:
tempLst.append(round(degrees(acos((c**2 - a**2 - b**2)/-2*a*b))))
这里的/-2*a*b会先算(c² -a² -b²)/-2,再乘以a*b,代入数值后得到的是-41690——这个数远小于acos要求的参数范围[-1, 1],直接触发了定义域错误!
正确的余弦定理公式应该是除以(-2*a*b),必须给-2*a*b加上括号,改成:
(c**2 - a**2 - b**2) / (-2 * a * b)
注意:你代码里所有钝角分支的余弦定理计算都有这个问题,包括a==d和b==d的部分,都要修正括号。
2. 隐藏的坑:角度和弧度混用
你在使用sin和asin时犯了一个常见错误:tempLst[0]是已经转成角度的数值(通过degrees()得到),但math.sin()的参数需要是弧度。比如这段代码:
tempLst.append(round(asin(a/sin(tempLst[0])*b)))
sin(tempLst[0])会把角度值当成弧度计算,结果完全错误,甚至可能让asin的参数也超出定义域。正确的做法是先把角度转回弧度:sin(radians(tempLst[0]))。
修正后的完整代码
我把所有问题都修复了,还做了一点小优化(比如统一余弦定理的写法、处理直角三角形的精度问题、最后排序角度):
from math import * def angles(a, b, c): # 先判断是否为合法三角形(加入微小误差容忍,避免浮点数精度问题) if a + b <= c + 1e-9 or a + c <= b + 1e-9 or c + b <= a + 1e-9: return [0, 0, 0] # 等边三角形(加入误差容忍,适配浮点数输入) elif abs(a - b) < 1e-9 and abs(b - c) < 1e-9: return [60, 60, 60] tempLst = [] d = max(a, b, c) if a == d: if (b ** 2 + c ** 2) < d**2 - 1e-9: # 钝角三角形:用余弦定理算最大角(标准公式更易读) angle_a = degrees(acos((b**2 + c**2 - a**2) / (2 * b * c))) tempLst.append(round(angle_a)) # 正弦定理算其他角,注意转弧度 angle_b = degrees(asin((b * sin(radians(tempLst[0]))) / a)) tempLst.append(round(angle_b)) else: # 锐角/直角三角形:用正弦定理或直接判断直角 if abs(a**2 - (b**2 + c**2)) < 1e-9: angle_b = degrees(asin(b/a)) angle_c = 90 - angle_b else: angle_b = degrees(asin(b/a)) angle_c = degrees(asin(c/a)) tempLst.append(round(angle_c)) tempLst.append(round(angle_b)) elif b == d: if (a**2 + c**2) < d**2 - 1e-9: angle_b = degrees(acos((a**2 + c**2 - b**2) / (2 * a * c))) tempLst.append(round(angle_b)) angle_a = degrees(asin((a * sin(radians(tempLst[0]))) / b)) tempLst.append(round(angle_a)) else: if abs(b**2 - (a**2 + c**2)) < 1e-9: angle_a = degrees(asin(a/b)) angle_c = 90 - angle_a else: angle_a = degrees(asin(a/b)) angle_c = degrees(asin(c/b)) tempLst.append(round(angle_c)) tempLst.append(round(angle_a)) else: # c是最大边 if (a**2 + b**2) < d**2 - 1e-9: angle_c = degrees(acos((a**2 + b**2 - c**2) / (2 * a * b))) tempLst.append(round(angle_c)) angle_b = degrees(asin((b * sin(radians(tempLst[0]))) / c)) tempLst.append(round(angle_b)) else: if abs(c**2 - (a**2 + b**2)) < 1e-9: angle_a = degrees(asin(a/c)) angle_b = 90 - angle_a else: angle_a = degrees(asin(a/c)) angle_b = degrees(asin(b/c)) tempLst.append(round(angle_a)) tempLst.append(round(angle_b)) # 计算第三个角,确保总和为180 third_angle = 180 - tempLst[0] - tempLst[1] tempLst.append(round(third_angle)) # 排序后返回,结果更直观 tempLst.sort() return tempLst
测试验证
现在运行angles(11,20,30),会返回[16, 33, 131](近似值),完全符合预期,不会再触发math domain error。
内容的提问来源于stack exchange,提问作者Elad Goldenberg
相关产品推荐
相关产品推荐

