Python实例题:Python计算二元二次方程组

目录

Python实例题

题目

代码实现

实现原理

方程组定义:

数值求解方法:

可视化功能:

关键代码解析

[1. 方程组定义](#1. 方程组定义)

[2. 求解函数](#2. 求解函数)

[3. 2D 图像绘制](#3. 2D 图像绘制)

使用说明

运行程序:

示例输入输出:

注意事项

局限性:

精度问题:

性能考虑:

扩展建议:

Python实例题

题目

Python计算二元二次方程组

代码实现

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import root
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm

def system_of_equations(vars, eq1_coeffs, eq2_coeffs):
    """
    定义二元二次方程组
    
    参数:
        vars (tuple): (x, y) 变量
        eq1_coeffs (list): 第一个方程的系数 [a1, b1, c1, d1, e1, f1]
        eq2_coeffs (list): 第二个方程的系数 [a2, b2, c2, d2, e2, f2]
    
    返回:
        list: 方程组的值 [eq1_value, eq2_value]
    """
    x, y = vars
    a1, b1, c1, d1, e1, f1 = eq1_coeffs
    a2, b2, c2, d2, e2, f2 = eq2_coeffs
    
    # 计算第一个方程的值
    eq1 = a1*x**2 + b1*x*y + c1*y**2 + d1*x + e1*y + f1
    
    # 计算第二个方程的值
    eq2 = a2*x**2 + b2*x*y + c2*y**2 + d2*x + e2*y + f2
    
    return [eq1, eq2]

def solve_system(eq1_coeffs, eq2_coeffs, initial_guesses=None):
    """
    求解二元二次方程组
    
    参数:
        eq1_coeffs (list): 第一个方程的系数 [a1, b1, c1, d1, e1, f1]
        eq2_coeffs (list): 第二个方程的系数 [a2, b2, c2, d2, e2, f2]
        initial_guesses (list): 初始猜测点列表,默认为None(使用默认猜测点)
    
    返回:
        list: 方程组的解 [(x1, y1), (x2, y2), ...]
    """
    solutions = []
    
    # 如果没有提供初始猜测点,使用默认的猜测点
    if initial_guesses is None:
        # 在常见区域设置多个初始猜测点
        initial_guesses = [
            (0, 0), (1, 1), (-1, -1), (10, 10), (-10, -10),
            (10, -10), (-10, 10), (0, 10), (0, -10), (10, 0), (-10, 0)
        ]
    
    # 对每个初始猜测点求解方程组
    for guess in initial_guesses:
        result = root(system_of_equations, guess, args=(eq1_coeffs, eq2_coeffs))
        
        # 检查求解是否成功
        if result.success:
            x, y = result.x
            
            # 检查解是否已经在列表中(考虑浮点数精度)
            is_duplicate = False
            for sol in solutions:
                if np.allclose([x, y], sol, rtol=1e-5, atol=1e-6):
                    is_duplicate = True
                    break
            
            if not is_duplicate:
                # 验证解是否同时满足两个方程
                eq1_val, eq2_val = system_of_equations([x, y], eq1_coeffs, eq2_coeffs)
                if abs(eq1_val) < 1e-6 and abs(eq2_val) < 1e-6:
                    solutions.append((x, y))
    
    return solutions

def plot_equations(eq1_coeffs, eq2_coeffs, solutions=None, x_range=(-10, 10), y_range=(-10, 10)):
    """
    绘制二元二次方程组及其解
    
    参数:
        eq1_coeffs (list): 第一个方程的系数 [a1, b1, c1, d1, e1, f1]
        eq2_coeffs (list): 第二个方程的系数 [a2, b2, c2, d2, e2, f2]
        solutions (list): 方程组的解,默认为None
        x_range (tuple): x轴范围,默认为(-10, 10)
        y_range (tuple): y轴范围,默认为(-10, 10)
    """
    # 创建网格
    x = np.linspace(x_range[0], x_range[1], 1000)
    y = np.linspace(y_range[0], y_range[1], 1000)
    X, Y = np.meshgrid(x, y)
    
    # 解析方程系数
    a1, b1, c1, d1, e1, f1 = eq1_coeffs
    a2, b2, c2, d2, e2, f2 = eq2_coeffs
    
    # 计算方程值
    Z1 = a1*X**2 + b1*X*Y + c1*Y**2 + d1*X + e1*Y + f1
    Z2 = a2*X**2 + b2*X*Y + c2*Y**2 + d2*X + e2*Y + f2
    
    # 创建图形
    plt.figure(figsize=(12, 10))
    
    # 绘制第一个方程的等高线(值为0的曲线)
    contour1 = plt.contour(X, Y, Z1, levels=[0], colors='blue', linewidths=2)
    plt.clabel(contour1, inline=True, fontsize=10)
    
    # 绘制第二个方程的等高线(值为0的曲线)
    contour2 = plt.contour(X, Y, Z2, levels=[0], colors='red', linewidths=2)
    plt.clabel(contour2, inline=True, fontsize=10)
    
    # 标记解点
    if solutions:
        for sol in solutions:
            plt.plot(sol[0], sol[1], 'go', markersize=10)
            plt.annotate(f'({sol[0]:.4f}, {sol[1]:.4f})', 
                         (sol[0], sol[1]), 
                         textcoords="offset points", 
                         xytext=(0,10), 
                         ha='center')
    
    # 添加标题和标签
    plt.title('二元二次方程组及其解', fontsize=16)
    plt.xlabel('x', fontsize=14)
    plt.ylabel('y', fontsize=14)
    plt.grid(True)
    
    # 添加图例
    plt.legend(['方程1', '方程2', '解'])
    
    # 显示图形
    plt.show()

def plot_3d_equations(eq1_coeffs, eq2_coeffs, solutions=None, x_range=(-10, 10), y_range=(-10, 10)):
    """
    绘制二元二次方程组的3D图像
    
    参数:
        eq1_coeffs (list): 第一个方程的系数 [a1, b1, c1, d1, e1, f1]
        eq2_coeffs (list): 第二个方程的系数 [a2, b2, c2, d2, e2, f2]
        solutions (list): 方程组的解,默认为None
        x_range (tuple): x轴范围,默认为(-10, 10)
        y_range (tuple): y轴范围,默认为(-10, 10)
    """
    # 创建网格
    x = np.linspace(x_range[0], x_range[1], 100)
    y = np.linspace(y_range[0], y_range[1], 100)
    X, Y = np.meshgrid(x, y)
    
    # 解析方程系数
    a1, b1, c1, d1, e1, f1 = eq1_coeffs
    a2, b2, c2, d2, e2, f2 = eq2_coeffs
    
    # 计算方程值
    Z1 = a1*X**2 + b1*X*Y + c1*Y**2 + d1*X + e1*Y + f1
    Z2 = a2*X**2 + b2*X*Y + c2*Y**2 + d2*X + e2*Y + f2
    
    # 创建3D图形
    fig = plt.figure(figsize=(12, 10))
    ax = fig.add_subplot(111, projection='3d')
    
    # 绘制第一个方程的曲面
    surf1 = ax.plot_surface(X, Y, Z1, cmap=cm.Blues, alpha=0.5, 
                           linewidth=0, antialiased=True)
    
    # 绘制第二个方程的曲面
    surf2 = ax.plot_surface(X, Y, Z2, cmap=cm.Reds, alpha=0.5, 
                           linewidth=0, antialiased=True)
    
    # 绘制z=0平面
    ax.plot_surface(X, Y, np.zeros_like(X), alpha=0.1, color='gray')
    
    # 标记解点(如果有解)
    if solutions:
        for sol in solutions:
            x_sol, y_sol = sol
            z_sol = 0  # 解点在z=0平面上
            ax.scatter(x_sol, y_sol, z_sol, color='green', s=100, marker='o')
            ax.text(x_sol, y_sol, z_sol, f'({x_sol:.4f}, {y_sol:.4f})', 
                   color='black', fontsize=12)
    
    # 添加标题和标签
    ax.set_title('二元二次方程组的3D图像', fontsize=16)
    ax.set_xlabel('x', fontsize=14)
    ax.set_ylabel('y', fontsize=14)
    ax.set_zlabel('方程值', fontsize=14)
    
    # 设置视角
    ax.view_init(elev=30, azim=45)
    
    # 添加图例
    fig.legend([surf1, surf2], ['方程1', '方程2'])
    
    # 显示图形
    plt.show()

def main():
    """主函数,处理用户输入并求解方程组"""
    try:
        print("="*50)
        print("        二元二次方程组求解器        ")
        print("="*50)
        
        print("\n请输入第一个方程的系数 (a1x² + b1xy + c1y² + d1x + e1y + f1 = 0):")
        a1 = float(input("  a1 = "))
        b1 = float(input("  b1 = "))
        c1 = float(input("  c1 = "))
        d1 = float(input("  d1 = "))
        e1 = float(input("  e1 = "))
        f1 = float(input("  f1 = "))
        
        print("\n请输入第二个方程的系数 (a2x² + b2xy + c2y² + d2x + e2y + f2 = 0):")
        a2 = float(input("  a2 = "))
        b2 = float(input("  b2 = "))
        c2 = float(input("  c2 = "))
        d2 = float(input("  d2 = "))
        e2 = float(input("  e2 = "))
        f2 = float(input("  f2 = "))
        
        # 构建系数列表
        eq1_coeffs = [a1, b1, c1, d1, e1, f1]
        eq2_coeffs = [a2, b2, c2, d2, e2, f2]
        
        # 求解方程组
        solutions = solve_system(eq1_coeffs, eq2_coeffs)
        
        # 输出结果
        print("\n" + "="*50)
        if solutions:
            print(f"方程组共有 {len(solutions)} 个实数解:")
            for i, sol in enumerate(solutions, 1):
                print(f"解 {i}: x = {sol[0]:.6f}, y = {sol[1]:.6f}")
        else:
            print("方程组没有找到实数解。")
        print("="*50)
        
        # 询问用户是否要绘制图像
        plot_option = input("\n是否绘制方程组图像?(y/n): ").lower()
        if plot_option == 'y':
            x_min = float(input("请输入x轴最小值: "))
            x_max = float(input("请输入x轴最大值: "))
            y_min = float(input("请输入y轴最小值: "))
            y_max = float(input("请输入y轴最大值: "))
            
            # 绘制2D图像
            plot_equations(eq1_coeffs, eq2_coeffs, solutions, 
                          (x_min, x_max), (y_min, y_max))
            
            # 询问是否绘制3D图像
            plot_3d_option = input("是否绘制3D图像?(y/n): ").lower()
            if plot_3d_option == 'y':
                plot_3d_equations(eq1_coeffs, eq2_coeffs, solutions, 
                                 (x_min, x_max), (y_min, y_max))
    
    except ValueError as ve:
        print(f"输入错误: {ve}")
    except Exception as e:
        print(f"发生错误: {e}")

if __name__ == "__main__":
    main()    

实现原理

这个二元二次方程组求解器基于以下技术实现:

方程组定义

  • 支持标准形式的二元二次方程组
  • 使用系数列表表示每个方程

数值求解方法

  • 使用 scipy.optimize.root 函数求解非线性方程组
  • 设置多个初始猜测点以寻找所有可能的解
  • 使用容差检查解的有效性和唯一性

可视化功能

  • 2D 图像展示两个方程的曲线及其交点
  • 3D 图像展示方程曲面与 z=0 平面的交线
  • 标记并显示所有实数解的坐标

关键代码解析

1. 方程组定义

python 复制代码
def system_of_equations(vars, eq1_coeffs, eq2_coeffs):
    x, y = vars
    a1, b1, c1, d1, e1, f1 = eq1_coeffs
    a2, b2, c2, d2, e2, f2 = eq2_coeffs
    
    eq1 = a1*x**2 + b1*x*y + c1*y**2 + d1*x + e1*y + f1
    eq2 = a2*x**2 + b2*x*y + c2*y**2 + d2*x + e2*y + f2
    
    return [eq1, eq2]

2. 求解函数

python 复制代码
def solve_system(eq1_coeffs, eq2_coeffs, initial_guesses=None):
    solutions = []
    
    if initial_guesses is None:
        initial_guesses = [
            (0, 0), (1, 1), (-1, -1), (10, 10), (-10, -10),
            (10, -10), (-10, 10), (0, 10), (0, -10), (10, 0), (-10, 0)
        ]
    
    for guess in initial_guesses:
        result = root(system_of_equations, guess, args=(eq1_coeffs, eq2_coeffs))
        
        if result.success:
            x, y = result.x
            
            # 检查解是否已存在并验证解的有效性
            is_duplicate = False
            for sol in solutions:
                if np.allclose([x, y], sol, rtol=1e-5, atol=1e-6):
                    is_duplicate = True
                    break
            
            if not is_duplicate:
                eq1_val, eq2_val = system_of_equations([x, y], eq1_coeffs, eq2_coeffs)
                if abs(eq1_val) < 1e-6 and abs(eq2_val) < 1e-6:
                    solutions.append((x, y))
    
    return solutions

3. 2D 图像绘制

python 复制代码
def plot_equations(eq1_coeffs, eq2_coeffs, solutions=None, x_range=(-10, 10), y_range=(-10, 10)):
    x = np.linspace(x_range[0], x_range[1], 1000)
    y = np.linspace(y_range[0], y_range[1], 1000)
    X, Y = np.meshgrid(x, y)
    
    a1, b1, c1, d1, e1, f1 = eq1_coeffs
    a2, b2, c2, d2, e2, f2 = eq2_coeffs
    
    Z1 = a1*X**2 + b1*X*Y + c1*Y**2 + d1*X + e1*Y + f1
    Z2 = a2*X**2 + b2*X*Y + c2*Y**2 + d2*X + e2*Y + f2
    
    plt.figure(figsize=(12, 10))
    
    # 绘制等高线(值为0的曲线)
    contour1 = plt.contour(X, Y, Z1, levels=[0], colors='blue', linewidths=2)
    contour2 = plt.contour(X, Y, Z2, levels=[0], colors='red', linewidths=2)
    
    # 标记解点
    if solutions:
        for sol in solutions:
            plt.plot(sol[0], sol[1], 'go', markersize=10)
            plt.annotate(f'({sol[0]:.4f}, {sol[1]:.4f})', 
                         (sol[0], sol[1]), 
                         textcoords="offset points", 
                         xytext=(0,10), 
                         ha='center')
    
    plt.title('二元二次方程组及其解', fontsize=16)
    plt.xlabel('x', fontsize=14)
    plt.ylabel('y', fontsize=14)
    plt.grid(True)
    plt.legend(['方程1', '方程2', '解'])
    plt.show()

使用说明

运行程序

bash 复制代码
python system_quadratic_solver.py
  • 输入方程系数: 按照提示依次输入两个方程的系数 \(a, b, c, d, e, f\)。

  • 查看结果: 程序会输出方程组的所有实数解,并可以选择绘制 2D 和 3D 图像以直观展示。

示例输入输出

python 复制代码
请输入第一个方程的系数 (a1x² + b1xy + c1y² + d1x + e1y + f1 = 0):
  a1 = 1
  b1 = 0
  c1 = 1
  d1 = 0
  e1 = 0
  f1 = -4

请输入第二个方程的系数 (a2x² + b2xy + c2y² + d2x + e2y + f2 = 0):
  a2 = 1
  b2 = 0
  c2 = -1
  d2 = 0
  e2 = 0
  f2 = 0

==================================================
方程组共有 4 个实数解:
解 1: x = 1.414214, y = 1.414214
解 2: x = 1.414214, y = -1.414214
解 3: x = -1.414214, y = 1.414214
解 4: x = -1.414214, y = -1.414214
==================================================

注意事项

局限性

  • 此程序只能找到实数解,无法找到复数解
  • 对于某些特殊方程组,可能需要调整初始猜测点
  • 数值方法可能无法找到所有解,尤其是当解的数量很多时

精度问题

  • 浮点数精度可能导致微小误差
  • 解的验证使用容差(1e-6),可根据需要调整

性能考虑

  • 绘制高分辨率图像可能需要较长时间
  • 复杂方程组可能需要更多的初始猜测点

扩展建议

  • 添加符号解法支持(使用 SymPy 库)
  • 实现解的稳定性分析
  • 增加交互式界面调整参数和查看结果
相关推荐
咖啡续命又一天1 小时前
Trae CN IDE自动生成注释功能测试与效率提升全解析
ide·python·ai编程
o独酌o1 小时前
鼠标的拖动效果
开发语言·javascript
张哈大1 小时前
【 java 集合知识 第二篇 】
java·开发语言·笔记·哈希算法
天才测试猿1 小时前
Postman接口测试之postman设置接口关联,实现参数化
自动化测试·软件测试·python·测试工具·职场和发展·接口测试·postman
miniwa1 小时前
Python编程精进:正则表达式
后端·python
青临的踩坑之路2 小时前
Docker + Nginx + Logrotate 日志管理与轮换实践
java·开发语言
十三画者2 小时前
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
python·机器学习·数据挖掘·数据分析·r语言·数据可视化
じ☆ve 清风°4 小时前
JavaScript 原型与原型链:深入理解 __proto__ 和 prototype 的由来与关系
开发语言·javascript·原型模式
程序员的世界你不懂8 小时前
Appium+python自动化(八)- 认识Appium- 下章
python·appium·自动化