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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:05:32