You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

代码出现math domain error:三角形判定与海伦公式问题排查求助

解决Python三角形代码中的math domain error及优化判定逻辑

问题根源

  1. 未拦截非法输入就执行面积计算:输入6、3、2时,三边无法构成三角形,但代码没有在调用面积计算函数前校验合法性,直接执行海伦公式。此时s*(s-a)*(s-b)*(s-c)结果为负数,math.sqrt()无法处理负数,因此抛出math domain error。
  2. 三角形判定逻辑错误:原function1的第二个条件用or是错误的——有效三角形要求所有两边之和都大于第三边,而非任意一边。同时代码未利用该函数的返回值控制后续流程,判定逻辑未起到实际作用。
  3. 海伦公式精度丢失:s = int(p/2)强制将半周长转为整数,会丢失精度(比如周长11时半周长是5.5,转int后变成5),导致计算结果错误。

修复与优化方案

1. 简化且正确的三角形判定

有效三角形的核心判定规则可简化为:最小两边之和 > 最大边。若该条件满足,另外两个边1+最大边>边2、边2+最大边>边1必然成立(最大边本身大于另外两边,加任何一边肯定大于第三边),代码更简洁高效。

2. 用判定结果控制流程

在计算面积前,先检查三角形是否合法,非法则跳过面积计算,避免触发错误。

3. 优化函数设计

  • 每个函数只负责单一职责(如判定合法性、计算周长、计算面积等),避免一个函数同时处理返回值和打印操作。
  • 修复海伦公式的精度问题,去掉不必要的int()转换。

修改后的完整代码

import math

# 获取用户输入
a = int(input('Enter your first triangle side '))
b = int(input('Enter your second triangle side '))
c = int(input('Enter your third triangle side '))

def is_valid_triangle(a, b, c):
    # 排序后直接判断最小两边之和是否大于最大边
    sorted_sides = sorted([a, b, c])
    return sorted_sides[0] + sorted_sides[1] > sorted_sides[2]

def is_right_triangle(a, b, c):
    sorted_sides = sorted([a, b, c])
    # 针对整数边的直角三角形判定
    return sorted_sides[0]**2 + sorted_sides[1]**2 == sorted_sides[2]**2

def calculate_perimeter(a, b, c):
    return a + b + c

def calculate_area(a, b, c):
    if not is_valid_triangle(a, b, c):
        return None
    perimeter = calculate_perimeter(a, b, c)
    semi_perimeter = perimeter / 2
    product = semi_perimeter * (semi_perimeter - a) * (semi_perimeter - b) * (semi_perimeter - c)
    # 处理退化三角形(乘积为0)的情况
    if product < 0:
        return None
    return math.sqrt(product)

def get_smallest_side(a, b, c):
    return min(a, b, c)

def get_medium_side(a, b, c):
    return sorted([a, b, c])[1]

def get_largest_side(a, b, c):
    return max(a, b, c)

# 主执行流程
if is_valid_triangle(a, b, c):
    print('This is a true triangle')
else:
    print('This is not a true triangle')

print('This is a right triangle' if is_right_triangle(a, b, c) else 'This is not a right triangle')

perimeter = calculate_perimeter(a, b, c)
print(f'The perimeter of the triangle is {perimeter}')

area = calculate_area(a, b, c)
if area is not None:
    print(f'The area of the triangle is {area:.2f}')
else:
    print('Cannot calculate area: invalid triangle')

print(f'Smallest Side: {get_smallest_side(a, b, c)}')
print(f'Medium Side: {get_medium_side(a, b, c)}')
print(f'Largest Side: {get_largest_side(a, b, c)}')

关键修改说明

  • 判定逻辑优化:通过sorted()排序后简化判定条件,避免冗余的多个or/and判断。
  • 错误拦截:在calculate_area中先校验三角形合法性,非法则返回None,主流程中判断后给出友好提示,不会触发math domain error。
  • 函数职责清晰:每个函数只做一件事,代码更易读、易维护。
  • 精度修复:保留半周长的浮点类型,确保海伦公式计算准确。
  • 流程可控:利用判定结果控制后续操作,确保非法输入不会进入错误的计算步骤。

内容的提问来源于stack exchange,提问作者Kio Lin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 04:10:57