Python制作一个线性代数计算小工具<1.0>

😜欢迎来阅!这里是一名Python小白,在Python的自学之旅中,他在畅游畅游~ 突然,好友发来消息(无中生友)😅问他一版线性代数的题目,他抚须长久,翻出尘封已久的《线性代数》一书…

⛹️‍♂️写在前面:

众所周知(自以为)👨‍🦳,在Python的numpy扩展包中有许多进行线性代数运算的函数👇👇在这里插入图片描述
再用上python内置的tkinter库进行GUI设计,我选取了Numpy中四个常用线性代数计算函数(inv、det、dot、solve),做了个线性代数计算小工具。
界面如下:
在这里插入图片描述

🏃‍♂️实现过程:

1️⃣GUI界面设计

(1) 首先,导入tkinter库,利用其相关函数搭好整个窗体界面,从上到下分为三部分,最上面的Frame框架用于放置功能按钮组件;中间的文本框用于用户按特定形式输出要计算的行列式或矩阵;最下面的标签用于展示计算结果。

import tkinter as tk

# 窗体
win = tk.Tk()
win.title("线性代数计算小工具1.0")
win.geometry('600x500')
# 按钮组件的框架
win_frame = tk.Frame(win, width=550, height=120, bg='#7cacae')
win_frame.pack()
# 文本输入框
win_Text1 = tk.Text(win, height=9, width=55, font=3)
win_Text1.pack()
# 标签(用于展示计算结果)
var = tk.StringVar()  # 文字变量储存器
win_label = tk.Label(win,
                     textvariable=var,  # 使用textvariable替换text使标签内容可变
                     bg="#e2e2e2",
                     font=('Arial', 15),
                     width=50, height=12)
win_label.pack()                                       

(2)添加按钮,将按钮添加到Frame框架中签到指定位置上去,并且设置按大小、按钮上的标签内容、指定点击时的触发功能命令。

tk.Button(win_frame,  # 要添加到的框架
          text='读入',  #按钮上的文本信息
          width=10, height=1,  # 按钮的宽高
          command=read).place(x=20, y=20)  # place设置按钮的放置位置
          #command为按钮的触发命令,需另外编写功能方法

tk.Button(win_frame,
          text='清空',
          width=10, height=1,
          command=clear).place(x=20, y=60)

tk.Button(win_frame,
          text='算逆矩阵',
          width=10, height=1,
          command=matrix_inv).place(x=130, y=20)

tk.Button(win_frame,
          text='算行列式',
          width=10, height=1,
          command=Determinant_det).place(x=130, y=60)

tk.Button(win_frame,
          text='矩阵相乘',
          width=10, height=1,
          command=matrix_dot).place(x=220, y=20)

tk.Button(win_frame,
          text='解线性方程',
          width=10, height=1,
          command=linear_solve).place(x=220, y=60)

(3)运行与展示,一定要在最后加上下面这行代码,才能将窗体程序运行出来得以展现。

win.mainloop()

运行展示如下:
在这里插入图片描述

2️⃣按钮功能实现

(1)【读入】按钮,该按钮的功能主要是获取输入到文本框中的内容,然后进行判断(判断要进行的运算),运用相关函数进行分割、替换等操作将文本框中的内容转换为特定格式的列表,并追加到指定的列表对象中用于后续运算。https://blog.csdn.net/m0_53156691/article/details/123549204
在这里插入图片描述

def read():  # 【读入】按钮功能
    text = win_Text1.get('0.0', 'end')  # 获取文本框所有内容
    try:
        if 'x' in text:
            a, b = text.split('x')  # 按'x'(小写X)进行分割成两个字符串对象
            a = a.strip()  # 去除字符串前后的空格内容
            b = b.strip()
            a1.append(a.replace('\n', ';'))  # 将字符中的换行符用";"替换并追加到列表中
            b1.append(b.replace('\n', ';'))
            tk.messagebox.showinfo(title='提示', message='读入成功!')  # 弹出框提示
        elif '=' in text:
            a, b = text.split('=')
            a = a.strip()
            b = b.strip()
            a1.append(a.replace('\n', ';'))
            b1.append(b.replace('\n', ';'))
            tk.messagebox.showinfo(title='提示', message='读入成功!')
        else:
            p = text.split('\n')  # 按换行符进行切分成一个列表
            p.pop()  # 将最后一个元素弹出(获取的文本内容最后是个空内容)
            for i in range(len(p)):
                p1 = p[i].split(' ')  # 将列表中每一块的的数字按空格进一步切分成列表
                intp1 = [int(x) for x in p1]  # 使用列表推导试将字符串转换为数字
                # intp1 = list(map(int, p1))  # 方法2 使用map做映射转换为数字
                matrix.append(intp1)  # 将转换后的数字列表追加存入列表
                tk.messagebox.showinfo(title='提示', message='读入成功!')
    except (Exception,) as e:
        print(e)
        tk.messagebox.showwarning(title='异常', message='输出数据或格式错误!')  # 异常的弹窗

(2)【清空】按钮,该按钮主要用于将三个列表对象清空,将文本框中的内容清空和标签上的输出结果清空。

def clear():  # 【清空】按钮功能
    matrix.clear()
    a1.clear()
    b1.clear()
    win_Text1.delete('1.0', 'end')
    var.set('')

(3)【算逆矩阵】按钮,先利用numpy中的array()函数将列表转换成数组,再利用numpy的子包linalg中的inv()函数进行逆矩阵的计算。
在这里插入图片描述

def matrix_inv():  # 【算逆矩阵】按钮功能
    try:
        n = np.array(matrix)
        var.set(np.linalg.inv(n))  # 计算逆矩阵函数,并将结果显示在标签上
    except (Exception,) as e:
        print(e)
        if len(matrix) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='该矩阵不为方阵,无法求逆矩阵')

(4)【算行列式】按钮,同样也是先利用numpy中的array()函数将列表转换成数组,然后再利用numpy的子包linalg中的det()函数进行行列式的计算,但行列式计算的结果为浮点数,长度过大会导致精度失真,这里又用round()方法将其保留小数点后三位有效数字输出。
在这里插入图片描述

def Determinant_det():  # 【算行列式】按钮功能
    try:
        n = np.array(matrix)
        print(n)
        var.set(round(np.linalg.det(n), 3))  # 计算行列式函数,并保留小数点后三位有效数字
    except (Exception,) as e:
        print(e)
        if len(matrix) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='该矩阵不为方阵,无法计算出其行列式的值')

(5)【矩阵相乘】按钮,矩阵相乘是两个矩阵间进行的运算,所以需要用两个对象链接数组对象,然后再利用numpy中的dot()函数进行运算得出结果。
在这里插入图片描述

def matrix_dot():  # 【矩阵相乘】按钮功能
    try:
        a2 = np.mat(a1[0])
        b2 = np.mat(b1[0])
        c = np.dot(a2, b2)  # 两个矩阵相乘函数
        var.set(c)
    except (Exception, TypeError) as e:
        print(e)
        if len(a1) == 0 or len(b1) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='此两个矩阵无法相乘')
            a1.clear()  # 这里清空列表是为了可以直接在文本进行修改后重新读入
            b1.clear()

(6)【解线性方程】按钮,在求解线性方程组的过程中往往是先写出其对应的增广矩阵,这里由于numpy的子包linalg中的solve()函数参数要求,需要分成系数矩阵和常数矩阵进行运算。(此外,有个小缺憾就是,当方程有无数解则无法给出运算结果)
在这里插入图片描述

在这里插入图片描述

def linear_solve():  # 【解线性方程】按钮功能
    try:
        a2 = np.mat(a1[0])
        b2 = np.mat(b1[0])
        c = np.linalg.solve(a2, b2)  # 计算线性方程函数
        var.set(c)  # 若是奇异矩阵则有无数解会报错
    except (Exception, ) as e:
        print(e)
        if len(a1) == 0 or len(b1) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='此两个矩阵不为非奇异矩阵,无唯一解')
            a1.clear()  # 这里清空列表是为了可以直接在文本进行修改后重新读入
            b1.clear()

🕺小小总结:

  • 写这种小程序还是挺简单的,只要很想法,愿意上手去做,实现起来并不是很困难。并且在编写代码的过程中自己的综合能力也会得到锻炼,而且当小程序按照你设想的效果运行起来的时候,不觉得很快乐有趣吗 哈哈!
  • 当然,可以看出,这个计算线性代数的小程序其实是很简陋的哈,只有几个简单的功能按钮,后续有时间可能会继续完善。有感兴趣的小伙伴也可以以此为参考做一个满足自己需求的这种小工具。
  • 欢迎大家与我交流!

✍完整代码

(供参考)

import tkinter as tk
from tkinter import messagebox
import numpy as np

# 窗体
win = tk.Tk()
win.title("线性代数计算小工具1.0")
win.geometry('600x500')
# 按钮组件的框架
win_frame = tk.Frame(win, width=550, height=120, bg='#7cacae')
win_frame.pack()
# 文本输入框
win_Text1 = tk.Text(win, height=9, width=55, font=3)
win_Text1.pack()
# 定义三个列表对象,用于后面存储读入的数据
matrix = []
a1 = []
b1 = []


def read():  # 【读入】按钮功能
    text = win_Text1.get('0.0', 'end')  # 获取文本框所有内容
    try:
        if 'x' in text:
            a, b = text.split('x')
            a = a.strip()
            b = b.strip()
            a1.append(a.replace('\n', ';'))
            b1.append(b.replace('\n', ';'))
            tk.messagebox.showinfo(title='提示', message='读入成功!')
        elif '=' in text:
            a, b = text.split('=')
            a = a.strip()
            b = b.strip()
            a1.append(a.replace('\n', ';'))
            b1.append(b.replace('\n', ';'))
            tk.messagebox.showinfo(title='提示', message='读入成功!')
        else:
            p = text.split('\n')  # 按换行符进行切分成一个列表
            p.pop()  # 将最后一个元素弹出(获取的文本内容最后是个空内容)
            for i in range(len(p)):
                p1 = p[i].split(' ')  # 将列表中每一块的的数字按空格进一步切分成列表
                intp1 = [int(x) for x in p1]  # 使用列表推导试将字符串转换为数字
                # intp1 = list(map(int, p1))  # 方法2 使用map做映射转换为数字
                matrix.append(intp1)  # 将转换后的数字列表追加存入列表
                tk.messagebox.showinfo(title='提示', message='读入成功!')
    except (Exception,) as e:
        print(e)
        tk.messagebox.showwarning(title='异常', message='输出数据或格式错误!')  # 异常的弹窗


def clear():  # 【清空】按钮功能
    matrix.clear()
    a1.clear()
    b1.clear()
    win_Text1.delete('1.0', 'end')
    var.set('')


def matrix_inv():  # 【算逆矩阵】按钮功能
    try:
        n = np.array(matrix)
        var.set(np.linalg.inv(n))  # 计算逆矩阵函数,并将结果显示在标签上
    except (Exception,) as e:
        print(e)
        if len(matrix) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='该矩阵不为方阵,无法求逆矩阵')


def Determinant_det():  # 【算行列式】按钮功能
    try:
        n = np.array(matrix)
        print(n)
        var.set(round(np.linalg.det(n), 3))  # 计算行列式函数,并保留小数点后三位有效数字
    except (Exception,) as e:
        print(e)
        if len(matrix) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='该矩阵不为方阵,无法计算出其行列式的值')


def matrix_dot():  # 【矩阵相乘】按钮功能
    try:
        a2 = np.mat(a1[0])
        b2 = np.mat(b1[0])
        c = np.dot(a2, b2)  # 两个矩阵相乘函数
        var.set(c)
    except (Exception, TypeError) as e:
        print(e)
        if len(a1) == 0 or len(b1) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='此两个矩阵无法相乘')
            a1.clear()  # 这里清空列表是为了可以直接在文本进行修改后重新读入
            b1.clear()


def linear_solve():  # 【解线性方程】按钮功能
    try:
        a2 = np.mat(a1[0])
        b2 = np.mat(b1[0])
        c = np.linalg.solve(a2, b2)  # 计算线性方程函数
        var.set(c)  # 若是奇异矩阵则有无数解会报错
    except (Exception, ) as e:
        print(e)
        if len(a1) == 0 or len(b1) == 0:
            tk.messagebox.showwarning(title='异常', message='未读入数据(矩阵为空)')
        else:
            tk.messagebox.showwarning(title='异常', message='此两个矩阵不为非奇异矩阵,无唯一解')
            a1.clear()  # 这里清空列表是为了可以直接在文本进行修改后重新读入
            b1.clear()


tk.Button(win_frame,
          text='读入',
          width=10, height=1,
          command=read).place(x=20, y=20)

tk.Button(win_frame,
          text='清空',
          width=10, height=1,
          command=clear).place(x=20, y=60)

tk.Button(win_frame,
          text='算逆矩阵',
          width=10, height=1,
          command=matrix_inv).place(x=130, y=20)

tk.Button(win_frame,
          text='算行列式',
          width=10, height=1,
          command=Determinant_det).place(x=130, y=60)

tk.Button(win_frame,
          text='矩阵相乘',
          width=10, height=1,
          command=matrix_dot).place(x=220, y=20)

tk.Button(win_frame,
          text='解线性方程',
          width=10, height=1,
          command=linear_solve).place(x=220, y=60)
tk.Label(win_frame,
         text='更多功能按钮ing!',
         bg='#99e2e2',
         font=(18,),
         width=18, height=3).place(x=350, y=20)

var = tk.StringVar()  # 文字变量储存器
win_label = tk.Label(win,
                     textvariable=var,  # 使用textvariable替换text使标签内容可变
                     bg="#e2e2e2",
                     font=('Arial', 15),
                     width=50, height=12)
win_label.pack()

win.mainloop()
  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值