Python隐式绘图异常:交点竖线不显示及程序报错问题求助
问题描述
我开发了一个基于Omar Khayyam方法、通过二次曲线求解三次方程的Python程序,需求是绘制两条曲线,并在它们的交点处添加一条从x轴延伸至交点的竖线。目前遇到两个问题:
- 竖线有时无法生成,仅在先显示绘图再追加时才会出现(可测试场景:选项1输入
b=24、c=159,或选项4输入a=15、c=-19)。调整plot3和plot2的渲染顺序有时能解决,但并非每次有效。 - 当程序检测到无正根并退出时,虽然会显示指定提示信息,但同时会抛出
An exception has occurred, use %tb to see the full traceback.的错误信息。
以下是程序代码:
import math import numpy as np import matplotlib.pyplot as plt import sympy as sym import sys from sympy import * from sympy.plotting import plot, plot_implicit, plot_parametric from sympy import sympify def find_intersection(F,G): result = sym.solve([F,G],(x,y)) return result def check_roots(roots): i=0 complexsol = 0 negativesol = 0 while i < 3: rx, ry = roots[i] if sympify(rx).is_real == True: if rx > 0: return rx, ry break else: print('Root ', i+1 , ' was discarded for being negative') negativesol = negativesol + 1 else: print('Root ', i+1, ' was discarded for being complex') complexsol = complexsol + 1 i+=1 if negativesol + complexsol == 3: sys.exit("There are no solutions by Khayyam's method") def plot_solution(F, G, xroot, yroot): newxroot = float(xroot) newyroot = float(yroot) x, y = symbols('x y') plot1 = plot_implicit(F, (x,0,2*newxroot), (y,0,2*newyroot), line_color='b',show=False) plot2 = plot_implicit(G, (x,0,2*newxroot), (y,0,2*newyroot), line_color='r',show=False) plot1.append(plot2[0]) plot3 = plot_implicit(Eq(x, newxroot),(x,0,newxroot), (y,0,newyroot), line_color='black', show=False) plot1.append(plot3[0]) plot1.show() print('Approximate x1 solution is: ', round(newxroot,1)) print('Exact x1 solution is: ', newxroot) print('Solving cubics using two conic sections in the sytle of Omar Khayyam') print('Cubic forms:') print('0: Cancel program') print('1: x^3 + bx = c') print('2: x^3 + ax^2 + bx + c = 0') print('3: x^3 + c = bx') print('4: x^3 + c = ax^2') print('5: x^3 + ax^2 = c') print('6: x^3 = bx + c') print('7: x^3 = ax^2 + c') userchoice = input('Please choose the form of your cubic or press 0 to cancel: ') if userchoice == '0': sys.exit('You have chosen to cancel the program') if userchoice == '1': # good choice is 15, -14 b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2/math.sqrt(b),y) eq2 = sym.Eq(b*x**2 + b*y**2, c*x) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '2': # good choice is -6,11,-6 a = int(input('Enter your a value: ')) b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq((x + a)*(y + b), a*b-c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '3': # good choice is 15, -14 b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y + c, b*x) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '4': # good choice is 15,-14 a = int(input('Enter your a value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y + c, a*y) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '5': # good choice is 15, -14 a = int(input('Enter your a value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y + a*y, c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '6': # good choice is 15, -14 b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y, b*x + c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '7': # good choice is 15, 19 a = int(input('Enter your a value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y, a*y + c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol)
解决方案
1. 修复竖线显示问题
plot_implicit绘制竖线时,若x区间仅包含到竖线位置,可能因渲染精度问题导致线条无法显示。改用plot函数直接绘制线段,稳定性更高:
修改plot_solution函数中的竖线绘制代码:
# 替换原plot3的定义 x_vals = [newxroot, newxroot] y_vals = [0, newyroot] plot3 = plot((x_vals[i], y_vals[i]) for i in range(2), line_color='black', show=False)
这种方式直接指定线段的两个端点,确保竖线从x轴准确延伸到交点。
2. 修复退出时的异常提示问题
sys.exit()在交互式环境中会触发异常回溯,改为先打印提示信息,再用sys.exit(0)正常退出(0表示无错误退出):
修改check_roots函数的退出逻辑:
if negativesol + complexsol == 3: print("There are no solutions by Khayyam's method") sys.exit(0)
同时把用户选择0退出的逻辑也同步修改:
if userchoice == '0': print('You have chosen to cancel the program') sys.exit(0)
完整修改后的代码
import math import numpy as np import matplotlib.pyplot as plt import sympy as sym import sys from sympy import * from sympy.plotting import plot, plot_implicit, plot_parametric from sympy import sympify def find_intersection(F,G): result = sym.solve([F,G],(x,y)) return result def check_roots(roots): i=0 complexsol = 0 negativesol = 0 while i < 3: rx, ry = roots[i] if sympify(rx).is_real == True: if rx > 0: return rx, ry else: print('Root ', i+1 , ' was discarded for being negative') negativesol = negativesol + 1 else: print('Root ', i+1, ' was discarded for being complex') complexsol = complexsol + 1 i+=1 if negativesol + complexsol == 3: print("There are no solutions by Khayyam's method") sys.exit(0) def plot_solution(F, G, xroot, yroot): newxroot = float(xroot) newyroot = float(yroot) x, y = symbols('x y') plot1 = plot_implicit(F, (x,0,2*newxroot), (y,0,2*newyroot), line_color='b',show=False) plot2 = plot_implicit(G, (x,0,2*newxroot), (y,0,2*newyroot), line_color='r',show=False) plot1.append(plot2[0]) # 直接绘制线段作为竖线 x_vals = [newxroot, newxroot] y_vals = [0, newyroot] plot3 = plot((x_vals[i], y_vals[i]) for i in range(2), line_color='black', show=False) plot1.append(plot3[0]) plot1.show() print('Approximate x1 solution is: ', round(newxroot,1)) print('Exact x1 solution is: ', xroot) print('Solving cubics using two conic sections in the style of Omar Khayyam') print('Cubic forms:') print('0: Cancel program') print('1: x^3 + bx = c') print('2: x^3 + ax^2 + bx + c = 0') print('3: x^3 + c = bx') print('4: x^3 + c = ax^2') print('5: x^3 + ax^2 = c') print('6: x^3 = bx + c') print('7: x^3 = ax^2 + c') userchoice = input('Please choose the form of your cubic or press 0 to cancel: ') if userchoice == '0': print('You have chosen to cancel the program') sys.exit(0) if userchoice == '1': # good choice is 15, -14 b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2/math.sqrt(b),y) eq2 = sym.Eq(b*x**2 + b*y**2, c*x) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '2': # good choice is -6,11,-6 a = int(input('Enter your a value: ')) b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq((x + a)*(y + b), a*b-c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '3': # good choice is 15, -14 b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y + c, b*x) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '4': # good choice is 15,-14 a = int(input('Enter your a value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y + c, a*y) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '5': # good choice is 15, -14 a = int(input('Enter your a value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y + a*y, c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '6': # good choice is 15, -14 b = int(input('Enter your b value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y, b*x + c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol) if userchoice == '7': # good choice is 15, 19 a = int(input('Enter your a value: ')) c = int(input('Enter your c value: ')) x, y = sym.symbols('x y') eq1 = sym.Eq(x**2,y) eq2 = sym.Eq(x*y, a*y + c) exact_sols = find_intersection(eq1,eq2) xsol, ysol = check_roots(exact_sols) plot_solution(eq1, eq2, xsol, ysol)
内容的提问来源于stack exchange,提问作者Bountifull
相关产品推荐
相关产品推荐

