[Python]Tkinter+Numpy+Matplotlib 进行的简单交互+曲线拟合+图像绘制【已改进】

用Python的Tkinter、Numpy、Matplotlib库对曲线拟合的一点探索【已改进】

需要用到的库:如标题
三大方面功能需要的库
一、简单交互,获取函数或者样本点tkinter[python自带]
二、处理所获得的信息,并得到绘图所需数据numpy,math
三、根据所得到的数据进行绘图matplotlib

首先得把需要的库给 import 喽,没有安装的库 pip install 一下也就OK啦

上码

from tkinter import *
import tkinter.messagebox as messagebox
from numpy import *
import numpy as np
import sys
import math
import matplotlib.pyplot as plt
import matplotlib
import matplotlib.gridspec as gridspec

一、 交互界面的设计[tkinter]

在这里插入图片描述

函数字符串为数据源部分功能tkinter相应实现模块
1函数字符串获取单选按钮
2插值区间选择滑动条
3随机获取样本点的数量微调框
4文字部分标签
5按钮部分按钮

在这里插入图片描述

样本点为数据源部分功能tkinter相应实现模块
1样本点获取文本框
2拟合阶数选取滑动条
3删除,添加,确认按键按钮
代码来了
class Miao(get_list, plot):
    def __init__(self):
        get_list.__init__(self)
        plot.__init__(self)

        self.master = Tk()
        self.xlst = [StringVar() for i in range(400)]
        self.ylst = [StringVar() for i in range(400)]
        self.etx = [Entry() for i in range(400)]
        self.ety = [Entry() for i in range(400)]
        self.entryfx = Entry()

        self.f_ = IntVar()  # 判断函数字符串是选择还是写入的标志
        self._fx = StringVar()  # 存储用户所选函数串
        self.fff = 0  # 判断是否进行函数选择, 否则
        self.num = StringVar()  # 判断数字框输入是否非法的字符串变量
        self.nm = IntVar()  # 存储样本点数量的整数型
        self._lx, self.lx_ = IntVar(), IntVar()  # 存储 x左右 范围(取点、插值、画图
        self.fx = IntVar()  # 选择项值获取
        self.paint = 0  # 判断,如果不是第一次绘图,就先清空画板
        self.ifpoint = 0  # 判断是样点作图还是函数作图
        self.point_ct = 0  # 统计样本点个数
        self.fdict = {
            0: 'cos(2*pi*x)*(e**(-x)) + 0.8',
            1: '1/(1+25*x**2)',
            2: '(e**(-x**2/2))/(2*pi)**0.5',
        }
        self.f_x = StringVar()  # 文本框获取值
        self.lst = []  # 存储 画图数据的列表
        self.ep = 10  # 插值区间长度初始值
        self.ojbk = 0
        self.master.title('插值法及函数图像简单拟合函数')
        # self.master.geometry('630x700+100+30')

        # 滚动条设定
        canvas = Canvas(self.master, confine=True, width=660, height=800, scrollregion=(-1, -1, 660, 1100))  # , bg='snow')
        scrollbar = Scrollbar(self.master, command=canvas.yview, bd=2)
        scrollbar.pack(side=RIGHT, fill=Y)
        canvas.pack(fill=Y)
        canvas.config(yscrollcommand=scrollbar.set)
        # 文字 (Label)
        title = Label(self.master, text='简单插值法以及曲线拟合', font=('黑体', 18), bg='turquoise', fg='black')
        title.pack(fill=X)
        canvas.create_window(280, 15, height=24, window=title, anchor=CENTER)

        # frame1 请您输入
        self.frame1 = Frame(canvas)
        self.frame1.pack(fill=X)
        label1 = Label(self.frame1, text='【1】请选择/输入一个函数:', font=('楷体', 14), fg='darkblue', bg='seashell')
        label1.grid(row=1, column=0, sticky=W)

        # 单选按钮
        fxx = [
            (0, "cos(2*pi*x)*(e**(-x)) + 0.8"),
            (1, "1/(1+25*x**2)"),
            (2, "(e**(-x**2/2))/(2*pi)**0.5"),
        ]
        j = 2
        for fid, fx in fxx:
            fx = Radiobutton(self.frame1, text=fx, fg='cornflowerblue', variable=self.fx, font=('楷体', 13), value=fid,
                             command=self.getfx)
            fx.grid(row=j, column=0, stick=W)
            j += 1
        fx = Radiobutton(self.frame1, text='手动输入函数', fg='cornflowerblue', variable=self.fx, font=('楷体', 13), value=3,
                         command=self.if_5)
        fx.grid(row=6, column=0, stick=W)
        fx = Radiobutton(self.frame1, text='输入样点数据', fg='cornflowerblue', variable=self.fx, font=('楷体', 13), value=4,
                         command=self.get_point)
        fx.grid(row=5, column=0, stick=W)
        canvas.create_window(20, 120, window=self.frame1, anchor=W)

        # 输入说明
        frame2 = Frame(canvas)
        frame2.pack()
        # 容器框 (LabelFrame)
        self.group = LabelFrame(frame2, text="函数输入说明", font='5', padx=5, pady=5, fg='red')
        self.group.grid()
        labels = [
            "1.平方‘**’来表示,绝对值:abs(x),乘号‘*’,除号‘/’,加减号‘+’ ‘-’",
            "2.支持无理数e的输入,圆周率用pi表示",
            "3.未知变量统一用x表示(只限用x表示),不支持中文符号输入(如中文输入法的括号。",
            "4.一些简单示例: sin(x), cos(x), cos(pi*x), e**x, (10-abs(x))**0.5,log(x)",
            "5.函数解析基于Python Numpy,有兴趣可以多尝试一些函数表达(4. 没列出的",
            "6.注意暂不支持纯数字输入! 若是输入log(x),请勿选择负区间,否则函数失效(开根号也如此)"
        ]
        for lb in labels:
            w = Label(self.group, text=lb, fg='darkcyan', font=('宋体', 10))
            w.grid(sticky=W)
        canvas.create_window(11, 290, window=frame2, anchor=W)

        # 区间选择  注意判断大小
        # frame4 请您输入
        self.frame4 = Frame(canvas)
        self.frame4.pack(fill=X)
        label4 = Label(self.frame4, text='【2】请选择一个取样区间:', font=('黑体', 14), fg='darkblue', bg='seashell')
        label4.grid(row=0, column=0, sticky=W)
        label4 = Label(self.frame4, text='  \n ')
        label4.grid(row=1, column=0, sticky=W)

        # 单选按钮  挡位
        frm = Frame(canvas)
        frm.pack()
        lab = Button(frm, relief='sunken', borderwidth=3, text='请选择档位:', font='12', fg='tomato')
        lab.grid(row=1, column=0, sticky=W)
        self.dwdict = {
            0: 'x1',
            1: 'x5',
            2: 'x10',
            3: 'x20',
            4: 'x0.1',
            5: 'x0.01',
            6: 'x0.001'
        }
        cl = 1
        self.dw = IntVar()
        for d in self.dwdict:
            dx = Radiobutton(frm, text=self.dwdict[d], fg='blue', variable=self.dw, font=('楷体', 14), value=d,
                             command=self.getdw)
            dx.grid(row=1, column=cl, stick=W)
            cl += 1
        canvas.create_window(15, 410, window=frm, anchor=W)

        # 滑动条 (Scale)
        self.lx = Scale(self.frame4, from_=-self.ep, to=self.ep, orient=HORIZONTAL, resolution=1, length=280, label="从",
                        tickinterval=5, relief=GROOVE)  # 默认垂直
        self.lx.grid(row=2, column=0, sticky=W)
        self.rx = Scale(self.frame4, from_=-self.ep, to=self.ep, orient=HORIZONTAL, resolution=1, length=280, label="到",
                        tickinterval=5, relief=RIDGE)  # 默认垂直
        self.rx.grid(row=2, column=1, sticky=W)
        canvas.create_window(10, 440, window=self.frame4, anchor=W)

        # 改变选区
        frameb = Frame(canvas)
        frameb.pack()
        low = Button(frameb, text='减小选择区间', borderwidth=4, font=('隶书', 11), command=self.lower, )
        low.grid(row=1, column=0, sticky=W)
        up = Button(frameb, text='扩大选择区间', borderwidth=4, font=('隶书', 11), command=self.upper, )
        up.grid(row=1, column=1, sticky=W)
        canvas.create_window(185, 530, window=frameb, anchor=W)

        #  插值点个数
        frame5 = Frame(canvas)
        frame5.pack(fill=X)
        label5 = Label(frame5, text='【3】请选择取样点个数', font=('黑体', 14), fg='darkblue', bg='seashell')
        label5.grid(row=2, column=0, sticky=W)
        self.number = Spinbox(frame5, borderwidth=2, relief='raised', font=10, textvariable=self.num, from_=3, to=500)
        self.number.grid(row=2, column=1, sticky=W)
        label51 = Label(frame5, text='[请选择或输入 3~500 间的整数]', fg='red')
        label51.grid(row=2, column=2)
        canvas.create_window(12, 565, window=frame5, anchor=W)

        # 输入说明
        framep = Frame(canvas)
        framep.pack()
        # 容器框 (LabelFrame)
        self.group = LabelFrame(framep, text="整体框架说明", font='4', padx=5, pady=5, fg='steelblue')
        self.group.grid()
        labels = [
            "一、插值法部分",
            " 1.由用户输入合法的函数字符串,选择取样区间及样本点个数;",
            " 2.确认输入无误后开始执行,相对随机进行样本点的获取;",
            " 3.由所得样本点经过拉格朗日/牛顿插值法、分段二次插值法、\n分段法再拟合出函数图;",
            " 4.最后展示拟合图像以及原图像\n",
            " 标注:分段二次插值法是照搬书上套路,分段法是将函数为三段:\n\r中间一段用拉格朗日/牛顿插值法得到\n\r两边两段用二次插值法得到",
            "\n二、最小二乘法部分",
            " 1.用户输入一系列样本点,并选择拟合函数的阶数进行拟合",
            " 2.由于一些原因,可能出现无法拟合,这时可以调整一下你和阶数",
            " 3.阶数说明:由于这里拟合默认拟合曲线方程为x的幂次多项式,阶数即是\nx的最高幂次",
            "",
        ]
        for lb in labels:
            w = Label(self.group, text=lb, fg='seagreen', font=('楷书', 11))
            w.grid(sticky=W)
        canvas.create_window(20, 840, window=framep, anchor=W)

        # ok按钮  (Button)
        framed = Frame(canvas)
        framed.pack()
        okk = Button(framed, relief='raised', borderwidth=5, text='确认输入', font=('楷书', 14), width=55, command=self.ok)
        okk.grid(row=1, column=0)
        canvas.create_window(10, 620, window=framed, anchor=W)

        framed1 = Frame(canvas)
        framed1.pack()
        okk = Button(framed1, relief='raised', borderwidth=4, text='点\n击\n退\n出', font=('楷书', 14), bg='red',
                     command=self.for_end)
        okk.grid(row=1, column=0)
        canvas.create_window(500, 100, window=framed1, anchor=W)

        framed2 = Frame(canvas)
        framed2.pack()
        end = Button(framed2, relief='raised', borderwidth=4, text='   确认输入   ', bg='aqua', font=('楷书', 14),
                     command=self.ok)
        end.grid(row=1, column=0)
        canvas.create_window(440, 170, window=framed2, anchor=W)

        self.master.mainloop()

    # 区间上升(主框架
    def upper(self):
        if self.ep < 20:
            self.ep += 5
            lb = 5
            self.lx = Scale(self.frame4, from_=-self.ep, to=self.ep, orient=HORIZONTAL, resolution=1, length=280,
                            label="从", tickinterval=lb, relief=GROOVE)  # 默认垂直
            self.lx.grid(row=2, column=0, sticky=W)
            self.rx = Scale(self.frame4, from_=-self.ep, to=self.ep, orient=HORIZONTAL, resolution=1, length=280,
                            label="到", tickinterval=lb, relief=RIDGE)  # 默认垂直
            self.rx.grid(row=2, column=1, sticky=W)

    # 区间下降(主框架
    def lower(self):
        if self.ep > 5:
            self.ep -= 5
            if self.ep > 5:
                lb = 5
            else:
                lb = 1
            self.lx = Scale(self.frame4, from_=-self.ep, to=self.ep, orient=HORIZONTAL, resolution=1, length=280,
                            label="从", tickinterval=lb, relief=GROOVE)  # 默认垂直
            self.lx.grid(row=2, column=0, sticky=W)
            self.rx = Scale(self.frame4, from_=-self.ep, to=self.ep, orient=HORIZONTAL, resolution=1, length=280,
                            label="到", tickinterval=lb, relief=RIDGE)  # 默认垂直
            self.rx.grid(row=2, column=1, sticky=W)

    # 按钮获取函数(主框架
    def getfx(self):
        self.entryfx.destroy()
        if self.ifpoint:
            try:
                self.pt.destroy()
            except:
                pass
        self.f_ = 0
        self.fff = 1
        self.ifpoint = 0
        self._fx = self.fdict[self.fx.get()]

    # 文本框中函数获取(主框架
    def if_5(self):
        self.f_ = 1  # 如果点击了 自己输入  标记self.f_ 为 1 否则为 0
        if self.ifpoint:
            try:
                self.pt.destroy()
            except:
                pass
        self.ifpoint = 0  # 判断是输入样本点还是函数字符串  字符 0  样本点 1
        # 输入框 (Entry)  #自我输入函数框图
        self.entryfx = Entry(self.frame1, textvariable=self.f_x, width=30)
        self.entryfx.grid(row=7, column=0, columnspan=4, sticky=W)

    # 获取插值点个数档位函数(主框架
    def getdw(self):
        self.dw_ = float(self.dwdict[self.dw.get()].strip('x'))

    # 判断 函数字符串输入结束, 开始画图(主框架
    # 改+++++
    def ok(self):
        self.ifpoint = 0
        self._lx, self.lx_ = self.lx.get() * self.dw_, self.rx.get() * self.dw_
        if self.f_ == 1:  # 捕捉获取的字符串
            self._fx = self.f_x.get()
        if self.fff == 0 and self.f_ != 1:
            self._fx = "cos(2*np.pi*x)*np.exp(-x) + 0.8"
        if self._lx > self.lx_:
            self._lx, self.lx_ = self.lx_, self._lx
        if not self.num.get().isdigit():
            messagebox.showwarning('Warining', '条目[3]非法输入')
        else:
            if not isinstance(type(eval(self.num.get())), int) and not 2 < eval(self.num.get()) < 501:
                messagebox.showwarning('Warining', '条目[3]非法输入')
            elif not self._fx:
                messagebox.showwarning('Warining', '函数输入为空')
            elif self._lx == self.lx_:
                self.warn1()
            else:
                self.nm = int(self.num.get())
                if messagebox.askokcancel('这是一个弹窗', '输入完成,是否开始下一步'):
                    self.ojbk = 1
                    lt = self.get_flist()
                    try:
                        self.s_plot(lt)
                    except Exception as t:
                        print(t)
                        messagebox.showerror('(*_*)', '运行失败了T_T')

    # 结束运行 关闭窗口(主框架
    def for_end(self):
        if messagebox.askokcancel('这是一个弹窗', '是否确认退出?'):
            sys.exit(0)

    #\ 获取样本点(开小框架获取样本店 框架0.1
    def get_point(self):
        if self.ifpoint == 1:
            try:
                self.pt.destroy()
            except:
                pass
        self.ifpoint = 1
        self.noinfo_window = 1  # 判断提示弹窗是否出现
        self.entryfx.destroy()
        self.point_ct = 0  # 统计样本点个数
        self.ex = []  # 置空刷新
        self.ey = []  # 置空刷新
        self.m = 1  # 阶数 默认为1
        global pd
        pd = Spinbox()
        self.pointdic = {}
        self.pt = Tk()
        self.pt.title('样本点获取')
        self.pt.geometry('350x500+800+30')

        # 滚动条设定
        canvas1 = Canvas(self.pt, confine=True, width=500, height=3000,
                         scrollregion=(0, 0, 500, 3000))  # , bg='snow')
        scrollbar = Scrollbar(self.pt, command=canvas1.yview, bd=2)
        scrollbar.pack(side=RIGHT, fill=Y)
        canvas1.pack(fill=Y)
        canvas1.config(yscrollcommand=scrollbar.set)
        # 文字 (Label)
        title = Label(self.pt, text='样本点获取', font=('黑体', 18), bg='lightblue', fg='black')
        title.pack(fill=X)
        canvas1.create_window(150, 15, height=24, window=title, anchor=CENTER)
        lbxy = Label(self.pt, text='X       \t   Y', font='10', )
        lbxy.pack(fill=X)
        canvas1.create_window(150, 140, height=24, window=lbxy, anchor=CENTER)

        # 拟合函数阶数
        frm1 = Frame(canvas1)
        frm1.pack(fill=X)

        lbl1 = Label(frm1, text='*请选择一个拟合函数阶数:', font=('黑体', 11), fg='darkblue')
        lbl1.grid(row=0, column=0, sticky=W)
        self.pdw = IntVar()
        pd = Spinbox(frm1, borderwidth=2, width=15, relief='raised', font=10, textvariable=self.pdw, from_=1, to=150)
        pd.grid(row=1, column=0, sticky=W)
        label51 = Label(frm1, text='[1~150 间的整数]', fg='red')
        label51.grid(row=1, column=1, sticky=W)
        canvas1.create_window(15, 100, window=frm1, anchor=W)

        # 数据文本框 系列
        self.frm2 = Frame(canvas1)
        self.frm2.pack()
        canvas1.create_window(150, 160, window=self.frm2, anchor=N)

        # 添加数据按钮
        button1 = Button(canvas1, text='添加数据', borderwidth=5, command=self.newp)
        canvas1.create_window(20, 50, window=button1, anchor=W)

        # 删除数据按钮
        button1 = Button(canvas1, text='删除上一数据', borderwidth=5, fg='red', command=self.del_last)
        canvas1.create_window(90, 50, window=button1, anchor=W)

        # 完成按钮
        button1 = Button(canvas1, text='输入完成', borderwidth=5, fg='blue', bg='snow', command=self.f_end)
        canvas1.create_window(250, 50, window=button1, anchor=W)

        self.pt.mainloop()

    #\ 创建新数据表  样本点(框架0.1
    def newp(self):
        if self.point_ct == 0 and self.noinfo_window:
            self.noinfo_window = 0
            messagebox.showinfo('输入小提示', "1.不支持数字外其他输入,比如符号,字母;\n2.可以x,y都为空,但不能只有一个值;\n3.x值可以不按照数轴顺序输入", )
        if self.point_ct < 400:
            self.etx[self.point_ct] = Entry(self.frm2, textvariable=self.xlst[self.point_ct])
            self.etx[self.point_ct].grid(row=self.point_ct, column=0, columnspan=1, )
            self.ety[self.point_ct] = Entry(self.frm2, textvariable=self.ylst[self.point_ct])
            self.ety[self.point_ct].grid(row=self.point_ct, column=2, columnspan=1, )
            self.point_ct += 1

    #\ 删除 最后输入样本点(框架0.1
    def del_last(self):
        if self.point_ct > 1:
            self.point_ct -= 1
            self.etx[self.point_ct].destroy()
            self.ety[self.point_ct].destroy()
            self.xlst[self.point_ct] = None
            self.ylst[self.point_ct] = None

    #\ 样本点输入结束(框架0.1
    def f_end(self):
        self.ifpoint = 1
        self.ex = []  # 置空刷新
        self.ey = []  # 置空刷新
        self.pointdic = {}
        if self.point_ct < 3:
            messagebox.showwarning('Warining', '样本点个数过少')
        elif not isinstance(type(eval(pd.get())), int) and not 0 < eval(pd.get()) < 151:
            messagebox.showwarning('Warining', '阶数非法输入')
        else:
            m = eval(pd.get())
            try:
                for i in range(self.point_ct):
                    et_x, et_y = self.etx[i].get(), self.ety[i].get()
                    if len(et_x) == len(et_y) == 0:
                        continue
                    else:
                        if not isinstance(type(eval(et_x)), (int, float)) and isinstance(type(eval(et_y)),
                                                                                         (int, float)):
                            messagebox.showwarning('Warining', '请检查输入是否合法(只能输入数字)\n[字母,符号,不输入都将报错]!')
                            self.pointdic.clear()
                            break
                        else:  # 已经确定两个数类型可靠
                            et_x, et_y = eval(et_x), eval(et_y)
                            if et_x in self.pointdic.keys():
                                messagebox.showwarning('Warining', 'X重复,请检查!')
                                self.pointdic.clear()
                                break
                            else:
                                self.pointdic[et_x] = et_y
                else:
                    keylst = list(self.pointdic.keys())
                    keylst = sorted(keylst)
                    for key in keylst:
                        self.ex.append(key)
                        self.ey.append(self.pointdic[key])
                    else:
                        if messagebox.askokcancel('这是一个弹窗', '输入完成,是否开始拟合'):
                            self.ojbk = 1
                            self.m = m
                            lt = self.get_flist()
                            lt1 = self.get_plist()
                            lt.append(lt[0])
                            lt[0], lt[1] = lt1[0], lt1[1]
                            self.p_plot(lt)  # 开始绘图
                            self.point_ct = 0  # 保证再一次进入到结束判断时字典、列表的存储位置从0开始
            except Exception as t:
                print(t)
                messagebox.showwarning('Warining', '错误!')

    # 警告 (主框架
    #def warn0(self):
        #messagebox.showwarning('Warining', '函数解析错误,函数不能为纯数字,或者包含其它非法字符')

    # 警告(主框架
    def warn1(self):
        messagebox.showwarning('Warining', '所选区间长度为空')

    # 错误(主框架
    def fail(self):
        messagebox.showerror('喵喵喵', '执行失败')

二、 数据处理部分[math,numpy]

函数数据处理
1获取原函数横纵坐标x,yx=numpy.arange(x0,xn, 0.001) +eval(fx)
2拉格朗日插值法数据获取------
3分段二次插值法------
4分段法(简单结合拉格朗日插值法与分段二次插值法)
样本点数据处理最小二乘法
代码来了
class get_list():
    def __init__(self):
        self.nm = None
        self.ojbk = None
        self.ifpoint = None
        self._lx = None
        self.lx_ = None
        self._fx = None
        self.dw_ = 1
        self.ex = None
        self.ey = None
        self.nh_fx = None
        self.m = 1
        self.fx_lst = []

    def s_set(self, *, _lx=None, lx_=None, _fx=None, nm=None):
        self.ojbk = 1
        self.ifpoint = 0
        self._lx = _lx
        self.lx_ = lx_
        self._fx = _fx
        self.nm = nm

    def p_set(self, *, ex=None, ey=None):
        self.ex = ex
        self.ey = ey

    # 处理字符串/样本点,返回一系列数据的列表【绘图数据获取】
    # 参数 self.nm(point_count), self.ojbk, self.ifpoint, self._lx,self.lx_, self._fx,
    # self.dw_, self.ex, self.ey,
    # return [x0, y0, x1, y1, x4, y4, x5, y5, y3]
    def get_flist(self):
        if not self.ojbk:
            quit(self.get_flist)

        if self.ifpoint == 0:  # 获取函数字符串数据
            n = self.nm  # 30  # 取样点个数( 相对随机 xk = xk + rand(0~1)*[(xn-x0)/n]
            m = 3  # 分段时左右两段取样点所占比重  sum(x1)/m
            limits = [self._lx, self.lx_]
            _x, x_, x_l = limits[0], limits[1], abs(limits[1] - limits[0])
            x1, y1 = [], []  # 存储样本点
            # 函数
            fx = self._fx
            if self.dw_ > 0.01:
                cont = 0.0001
            else:
                cont = 0.00001
            dex = x_l * 0.25
            # 获取原函数画图所需点列表 x0, y0  (插值拟合数据源
            x = np.arange(_x - dex, x_ + dex, cont)
            eval(fx)
            try:
                y0 = eval(fx)
                if len(y0) == 1:
                    messagebox.showwarning('Warining', '函数解析错误,函数不能为纯数字,或者包含其它非法字符')
                    return None
            except Exception as t:
                print(t)
                messagebox.showwarning('Warining', '函数解析错误,函数不能为纯数字,或者包含其它非法字符')
                return None
            x0 = x
            # 获取样本点并存入列表 x1, y1  (折线图数据源
            for xo in np.linspace(_x, x_, n):
                x = xo + np.random.rand() * (x_l / n)
                x1.append(x)
                y1.append(eval(fx))
        else:  # 样本点  初始化 参数:self.ex; self.ey; self.m; self.ifpoint; self.nh_fx
            x1, y1 = self.ex, self.ey
            dex = (self.ex[-1] - self.ex[0]) * 0.2
            n = len(x1)
            m = 2  # 不需要
            cont = 0.0001
            x0 = np.arange(x1[0] - dex, x1[-1] + dex, cont)
        # 拟合所需 1_原函数 x0, y0; 2_取样点 x1, y1; 3_取样点个数 n, 取样精度 cnt
        '''
        # 拉格朗日插值法 获得 y2
        y2 = x0 * 0
        for i in range(n):
            fz, fm = x0* 0 + 1, 1
            for j in range(n):
                if not j==i:
                    fz *= (x0 - x1[j])
                    fm *= (x1[i] - x1[j])
            y2 += y1[i] * (fz / fm)

        '''
        # 牛顿插值法 获得 y3
        y3 = x0 * 0 + y1[0]
        x3 = x0 * 0 + 1
        y4 = [y1, []]
        #   获得差商标
        for i in np.arange(1, n)[::-1]:
            x3 *= (x0 - x1[n - 1 - i])
            for j in range(i):
                ff = (y4[0][j + 1] - y4[0][j]) / (x1[n - i + j] - x1[j])
                y4[1].append(ff)
            y3 += y4[1][0] * x3
            y4 = [y4[1], []]
        # 分段二次数插值法  ----1段式  (相当于 m==2)
        x5, y5 = [], []  # 存取插值函数数据
        # 左右两部分取样点下标列表
        lln = len(x1)
        sq = list(range(0, lln - 2, 2))
        for i in range(0, lln - 2, 2):  #
            if i == 0:
                if i == sq[-1]:
                    dx1_ = 3 * dex
                else:
                    dx1_ = 0
                dx1 = dex
            elif i == sq[-1]:
                dx1 = 0
                dx1_ = 3*dex
            else:
                dx1 = 0
                dx1_ = 0
            fz5, fm5 = np.arange(x1[i] - dx1, x1[i + 2] + dx1_, cont) * 0 + 1, 1

            y_y = np.arange(x1[i] - dx1, x1[i + 2] + dx1_, cont) * 0  # 累加获得小段函数值数据源
            x_x = np.arange(x1[i] - dx1, x1[i + 2] + dx1_, cont)  # 获取当前区间 x 的列表 x
            for k in range(i, i + 3):
                fz5, fm5 = fz5 * 0 + 1, 1
                for j in range(i, i + 3):
                    if not j == k:
                        fz5 *= (x_x - x1[j])
                        fm5 *= (x1[k] - x1[j])
                y_y += y1[k] * (fz5 / fm5)
            y5 += list(y_y)
            x5 += list(x_x)

        # 分段插值法  ----三段式
        y4, y4_ = [], []  # 存取左半边插值函数数据
        x4, x4_ = [], []  # 右半边数据存储
        # 左右两部分取样点下标列表
        ltx, rtx = list(range(0, int(len(x1) // m), 2)), list(range(int((1 - 1 / m) * len(x1)), len(x1), 2))
        rtx.pop(-1)
        for i in ltx:  # 左半部分
            if i == 0:
                dx0 = dex
            else:
                dx0 = 0
            fz, fm = np.arange(x1[i] - dx0, x1[i + 2], cont) * 0 + 1, 1
            yy = np.arange(x1[i] - dx0, x1[i + 2], cont) * 0  # 累加获得小段函数值数据源
            l_x = np.arange(x1[i] - dx0, x1[i + 2], cont)  # 获取当前区间 x 的列表 left_x
            for k in range(i, i + 3):
                fz, fm = fz * 0 + 1, 1
                for j in range(i, i + 3):
                    if not j == k:
                        fz *= (l_x - x1[j])
                        fm *= (x1[k] - x1[j])
                yy += y1[k] * (fz / fm)
            y4 = y4 + list(yy)
            x4 += list(l_x)
        for i_ in rtx:  # 右半部分
            if i_ == rtx[-1]:
                dx0 = dex
            else:
                dx0 = 0
            fz_, fm_ = np.arange(x1[i_], x1[i_ + 2] + dx0, cont) * 0 + 1, 1
            yy_ = np.arange(x1[i_], x1[i_ + 2] + dx0, cont) * 0
            x_r = np.arange(x1[i_], x1[i_ + 2] + dx0, cont)
            for k_ in range(i_, i_ + 3):
                fz_, fm_ = fz_ * 0 + 1, 1
                for j_ in range(i_, i_ + 3):
                    if not j_ == k_ and j_ < len(x1) and k_ < len(x1):
                        fz_ *= (x_r - x1[j_])
                        fm_ *= (x1[k_] - x1[j_])
                if k_ < len(x1):
                    yy_ += y1[k_] * (fz_ / fm_)
            y4_ = y4_ + list(yy_)
            x4_ += list(x_r)

        # 由中间向两边遍历循环,寻找 左 中,中 右最佳连接点
        if m == 2:
            left = right = 0
        else:
            start1 = start = len(x0) // 2
            while 1:
                if n < 7:
                    left = right = 0
                    break
                if x0[start] < x4[-1] and start:  # 左连接点
                    left = start + 1
                    start = 0
                if x0[start1] > x4_[0] and start1:  # 右连接点
                    right = start1 - 1
                    start1 = 0
                if start:
                    start -= 1
                if start1:
                    start1 += 1
                if not (start + start1):
                    break
        y4 = y4 + list(y3[left:right]) + y4_  # 拼接 左中右 函数值数据源
        x4 = x4 + list(x0[left:right]) + x4_  # 拼接 左中右 自变量值
        if n < 7:
            x4, y4 = [], []
        if self.ifpoint:
            y0 = []
        return [x0, y0, x1, y1, x4, y4, x5, y5, y3]

    # 获取输入样本点 最小二乘法拟合曲线数据【绘图数据获取】
    # 参数 self.nh_fx, self.ex, self.ey, self.m,
    # return [x, y]
    def get_plist(self):
        self.nh_fx = ''
        ex = self.ex  # np.arange(-10, -4,0.1)       #[1,3,4,5,6,7,8,9,10]
        ey = self.ey  # eval("cos(2*np.pi*ex)*np.exp(-ex) + 0.8")#eval("sin(ex)")##[10,5,4,2,1,1,2,3,4]
        x_or_cplx = 1  # 判断是简单 x 线性函数拟合还是  自定义函数拟合
        if x_or_cplx == 1:  # x 线性拟合
            m = self.m
            b = [0 for i in range(m + 1)]  # 存储
            fai = [0 for i in range(2 * m + 1)]  # 存储 x 的 0~2m次方
            A = [[0 for i in range(m + 1)] for i in range(m + 1)]  # 存储 A 矩阵 Ax = b
            for i in range(2 * m + 1):
                for j in range(len(ex)):
                    fai[i] += ex[j] ** i
                    if i < m + 1:
                        b[i] += ey[j] * (ex[j] ** i)
            for i in range(m + 1):
                for j in range(m + 1):
                    A[i][j] = fai[i + j]
            try:
                a = np.linalg.solve(A, b)  # .resize(1, len(b))  [32, 147, 1025, 8421, 74261]
            except Exception as t:
                print(t)
                a = [1,]
                pass
            #print(A, b, a, sep='\n')
            self.nh_fx += f"$({a[0]:.4e})"
            for i in range(m):
                if i!=0 and not i%9:
                    self.nh_fx += '\n'
                self.nh_fx += f"+({a[i+1]:.4e})X^{i+1}"
            self.nh_fx = self.nh_fx + "$  \n[Least-Square-method]"
            if m>9:
                self.nh_fx = self.nh_fx.replace('$', '')
            dex = (ex[-1] - ex[0]) * 0.1
            x = np.arange(ex[0] - dex, ex[-1] + dex, 0.001)
            y = x * 0
            for i in range(m + 1):
                y += a[i] * (x ** i)
        else:
            m = 3
            b = [0 for i in range(m + 1)]  # 存储 fn * yn
            A = [[0 for i in range(m + 1)] for i in range(m + 1)]  # 存储 A 矩阵 Ax = b
            ff = ['self.f0(xm)', 'self.f1(xm)', 'self.f2(xm)', 'self.f3(xm)',] # 'self.f4(xm)', 'self.f5(xm)', 'self.f6(xm)']
            for i in range(m + 1):
                for j in range(i, m + 1):
                    n = 0
                    for xm in ex:
                        A[i][j] += eval(ff[j]) * eval(ff[i])
                        if i == 0:
                            b[j] += ey[n] * eval(ff[j])
                            n += 1
            for i in range(m + 1):
                for j in range(0, i):
                    A[i][j] = A[j][i]

            try:
                a = np.linalg.solve(A, b)  # .resize(1, len(b))
            except:
                pass
            self.nh_fx += f"$({a[0]:.4e})"
            for i in range(m):
                if i!=0 and not i%9:
                    self.nh_fx += '\n'
                self.nh_fx += f"+({a[i+1]:.4e})x({self.fx_lst[i]})"
            self.nh_fx = self.nh_fx + "$  \n[Least-Square-method]"
            if m>9:
                self.nh_fx = self.nh_fx.replace('$', '')
            dex = (ex[-1] - ex[0]) * 0.11
            x = np.arange(ex[0] - dex, ex[-1] + dex, 0.001)
            y = x * 0

            xm = x
            for i in range(m + 1):
                y += a[i] * eval(ff[i])
        return [x, y]

    def f0(self, xn):
        return 1

    def f1(self, xn):
        if 'cos(2pi*x)(1/e^x)' not in self.fx_lst:
            self.fx_lst.append('cos(2pi*x)(1/e^x)')
        return cos(2*np.pi*xn)*np.e**(-xn)

    def f2(self, xn):
        if 'cos(2pi*x)' not in self.fx_lst:
            self.fx_lst.append('cos(2pi*x)')
        return cos(2*pi*xn)

    def f3(self, xn):
        if 'e^x' not in self.fx_lst:
            self.fx_lst.append('e^x')
        return np.e**(xn)

三、 绘图[matplotlib]

函数字符串部分
  • 拉格朗日、分段二次、分段法与原函数同坐标系绘图比较+所选样本点散点图
  • 不同方法函数 单独图像
  • 原函数小图
  • 图标
样本点处理后绘图部分
  • 最小二乘法、拉格朗日、分段二次法函数图同坐标系绘图比较
  • 样本点散点图
  • 图标
代码来了
class plot():
    def __init__(self):
        self.ojbk = None
        self.ifpoint = None
        self._lx = None
        self.lx_ = None
        self.paint = None
        self.nh_fx = None

        # 画图【绘图】
        # 参数 lst, self.ojbk, self.ifpoint, self._lx, self.lx_, self.paint

    def s_plot(self, lst):  # 画图
        if not self.ojbk or not lst:
            return None
        matplotlib.rcParams['font.family'] = 'SimHei'
        matplotlib.rcParams['font.sans-serif'] = ['SimHei']
        matplotlib.rcParams['axes.unicode_minus'] = False  # 中文负号问题

        plt.figure(num='插值法以及曲线拟合的一点探索', figsize=(15, 15), dpi=110, facecolor='w', edgecolor='cyan')
        gs = gridspec.GridSpec(2, 4)
        ax1 = plt.subplot(gs[0:, :2])  # mix  原图 x0, y0
        ax2 = plt.subplot(gs[0, 2:])  # 牛顿/拉格朗日插值 x0, y2
        ax3 = plt.subplot(gs[1, 2])  # 分段二次插值    x4, y4
        ax4 = plt.subplot(gs[1, 3])  #    x1, y1
        x0, y0 = lst[0], lst[1]  # mix  原图 x0, y0
        x1, y1 = lst[2], lst[3]  #  x1, y1  散点图
        x4, y4 = lst[4], lst[5]  # 分段插值    x4, y4
        x5, y5 = lst[6], lst[7]  #
        y2 = lst[8]  # 牛顿/拉格朗日插值 x0, y2

        if self.ifpoint == 0:
            x0_ = x0
            mn, mx = min(y0), max(y0)
            if math.isnan(mn):
                mn = -20
            if math.isnan(mx):
                mx = 20
            dy = abs(mx - mn) / 8
            foc_y = mn + (mx - mn) * 0.35
            mn, mx = mn - dy, mx + dy
            foc = (self._lx + self.lx_) / 2  # 横坐标与纵坐标交点
        else:
            x0_ = []
            mn, mx = min(y1), max(y1)
            dy = abs(mx - mn) / 8
            foc_y = mn + (mx - mn) * 0.35
            mn, mx = mn - dy, mx + dy
            foc = (x1[0] + x1[-1]) / 2  # 横坐标 与纵坐标交点处x 的值

        if self.paint != 0:
            for ax in [ax1, ax2, ax3, ax4]:
                ax.cla()
        ax1.plot(x0_, y0, color='r', label=r'$Original-function$', linewidth=1.5, alpha=.98)
        ax1.scatter(x1, y1, s=50, marker="o", label=r'Sample-point', color='lime', alpha=.79)
        ax1.plot(x0, y2, color='darkviolet', label=r"$Lagrange's/Newton-interpolation$", linewidth=.8)
        ax1.plot(x5, y5, color='blue', label=r'$Piecewise-interpolation$', linewidth=.7)
        ax1.plot(x4, y4, color='peru', label=r'$Simple-Piecewise-interpolation$', linewidth=.7, alpha=0.95)
        # 小图
        mini = plt.figure(num='插值法以及曲线拟合的一点探索').add_axes([.02, .8, .15, .15])
        if self.paint != 0:
            mini.cla()
        mini.plot(x0_, y0, color='r', linewidth=1)
        mini.spines['top'].set_color('none')
        mini.spines['right'].set_color('none')
        mini.xaxis.set_ticks_position('bottom')
        mini.yaxis.set_ticks_position('left')
        mini.spines['bottom'].set_position(('data', foc_y))
        mini.spines['left'].set_position(('data', foc))
        mini.set_title(r'原函数')

        ax1.set_title('函数图比较')

        ax2.plot(x0, y2, color='darkviolet', linewidth=1, alpha=.9)
        ax2.scatter(x1, y1, s=50, marker="o", color='lime', alpha=.8)
        ax2.set_title('拉格朗日/牛顿插值法')

        ax3.plot(x5, y5, color='blue', linewidth=1)
        ax3.scatter(x1, y1, s=50, marker="o", color='lime', alpha=.8)
        ax3.set_title('分段二次插值法')

        ax4.plot(x4, y4, color='peru', linewidth=1)
        ax4.scatter(x1, y1, s=50, marker="o", color='lime', alpha=.8)
        ax4.set_title('简单分段插值法')
        plt.figlegend(loc='upper center')

        for ax in [ax1, ax2, ax3, ax4]:
            ax.spines['top'].set_color('none')
            ax.spines['right'].set_color('none')
            ax.xaxis.set_ticks_position('bottom')
            ax.yaxis.set_ticks_position('left')
            ax.spines['bottom'].set_position(('data', foc_y))
            ax.spines['left'].set_position(('data', foc))
            ax.axis([x0[0], x0[-1], mn, mx])

        # 拉格朗日 插值 大图
        plt.figure(num='拉格朗日/牛顿插值法', figsize=(10, 10))
        if self.paint != 0:
            plt.clf()
        plt.plot(x0, y2, color='blueviolet', label=r"$Lagrange's/Newton-interpolation$", linewidth=.8)
        plt.title('拉格朗日/牛顿插值法')
        plt.plot(x0_, y0, color='red', label=r'$Original-function$', linewidth=.8)
        plt.scatter(x1, y1, s=50, marker="o", label=r'Sample-point', color='lime', alpha=.8)
        plt.legend(loc='best')
        plt1 = plt.gca()
        plt1.spines['top'].set_color('none')
        plt1.spines['right'].set_color('none')
        plt1.xaxis.set_ticks_position('bottom')
        plt1.yaxis.set_ticks_position('left')
        plt1.spines['bottom'].set_position(('data', foc_y))
        plt1.spines['left'].set_position(('data', foc))
        plt.axis([x0[0], x0[-1], mn - 2 * dy, mx])
        # 小图
        mini = plt.figure(num='拉格朗日/牛顿插值法').add_axes([.02, .75, .22, .22])
        if self.paint != 0:
            mini.cla()
        mini.plot(x0_, y0, color='r', linewidth=1)
        mini.spines['top'].set_color('none')
        mini.spines['right'].set_color('none')
        mini.xaxis.set_ticks_position('bottom')
        mini.yaxis.set_ticks_position('left')
        mini.spines['bottom'].set_position(('data', foc_y))
        mini.spines['left'].set_position(('data', foc))
        mini.set_title(r'原函数')


        # 分段法2 大图
        plt.figure(num='简单分段插值法', figsize=(10, 10))
        if self.paint != 0:
            plt.clf()
        plt.plot(x4, y4, color='teal', label=r'$Simple-Piecewise-interpolation$', linewidth=1)
        plt.title('简单分段插值法')
        plt.plot(x0_, y0, color='red', label=r'$Original-function$', linewidth=1)
        plt.scatter(x1, y1, s=50, marker="o", label=r'Sample-point', color='lime', alpha=.8)
        plt.legend(loc='best')
        plt1 = plt.gca()
        plt1.spines['top'].set_color('none')
        plt1.spines['right'].set_color('none')
        plt1.xaxis.set_ticks_position('bottom')
        plt1.yaxis.set_ticks_position('left')
        plt1.spines['bottom'].set_position(('data', foc_y))
        plt1.spines['left'].set_position(('data', foc))
        plt.axis([x0[0], x0[-1], mn - 2 * dy, mx])
        # 小图
        mini = plt.figure(num='简单分段插值法').add_axes([.02, .75, .22, .22])
        if self.paint != 0:
            mini.cla()
        mini.plot(x0_, y0, color='r', linewidth=1)
        mini.spines['top'].set_color('none')
        mini.spines['right'].set_color('none')
        mini.xaxis.set_ticks_position('bottom')
        mini.yaxis.set_ticks_position('left')
        mini.spines['bottom'].set_position(('data', foc_y))
        mini.spines['left'].set_position(('data', foc))
        mini.set_title(r'原函数')


        # 分段法1 大图
        plt.figure(num='分段二次插值法', figsize=(10, 10))
        if self.paint != 0:
            plt.clf()
        plt.plot(x5, y5, color='teal', label=r'$Piecewise-interpolation$', linewidth=1)
        plt.title('分段二次插值法')
        plt.plot(x0_, y0, color='red', label=r'$Original-function$', linewidth=1)
        plt.scatter(x1, y1, s=50, marker="o", label=r'Sample-point', color='lime', alpha=.8)
        plt.legend(loc='best')
        plt1 = plt.gca()
        plt1.spines['top'].set_color('none')
        plt1.spines['right'].set_color('none')
        plt1.xaxis.set_ticks_position('bottom')
        plt1.yaxis.set_ticks_position('left')
        plt1.spines['bottom'].set_position(('data', foc_y))
        plt1.spines['left'].set_position(('data', foc))
        plt.axis([x0[0], x0[-1], mn - 2 * dy, mx])
        # 小图
        mini = plt.figure(num='分段二次插值法').add_axes([.02, .75, .22, .22])
        if self.paint != 0:
            mini.cla()
        mini.plot(x0_, y0, color='r', linewidth=1)
        mini.spines['top'].set_color('none')
        mini.spines['right'].set_color('none')
        mini.xaxis.set_ticks_position('bottom')
        mini.yaxis.set_ticks_position('left')
        mini.spines['bottom'].set_position(('data', foc_y))
        mini.spines['left'].set_position(('data', foc))
        mini.set_title(r'原函数')

        self.paint = 1
        plt.show()
        plt.close()

        # 最小二乘法绘图【绘图】
        # 参数 lst, self.nh_fx
    def p_plot(self, lst):
        matplotlib.rcParams['font.family'] = 'SimHei'
        matplotlib.rcParams['font.sans-serif'] = ['SimHei']
        matplotlib.rcParams['axes.unicode_minus'] = False  # 中文负号问题
        x0, y0 = lst[0], lst[1]  # 二乘法
        x1, y1 = lst[2], lst[3]  # 散点图
        x5, y5 = lst[6], lst[7]  # 分段二次插值
        x2, y2 = lst[9], lst[8]  # 拉格朗日
        up, low = max(y0), min(y0)
        if math.isnan(up):
            up = -20
        if math.isnan(low):
            low = 20
        ddy = (up - low) * 0.2
        xup, xlow = max(x1), min(x1)
        ddx = (xup - xlow) * 0.23
        plt.figure(num='最小二乘法、拉格朗日插值法、分段二次插值法拟合曲线比较', figsize=(10, 10))
        # plt.title('')
        plt.clf()
        plt.plot(x0, y0, color='red', label=self.nh_fx, linewidth=2, alpha=.98)  # r'$Least-Square-method$' 最小二乘
        plt.scatter(x1, y1, s=50, marker="x", label=r'Sample-point', color='black', alpha=1)  # 散点
        plt.plot(x2, y2, color='darkviolet', label=r"$Lagrange's/Newton-interpolation$", linewidth=0.7)   # 拉格朗日
        plt.plot(x5, y5, color='blue', label=r'$Piecewise-interpolation$', linewidth=.7)   #分段二次
        plt.figlegend(loc='upper left')
        plt1 = plt.gca()
        plt1.spines['top'].set_color('none')
        plt1.spines['right'].set_color('none')
        plt1.xaxis.set_ticks_position('bottom')
        plt1.yaxis.set_ticks_position('left')
        plt1.spines['bottom'].set_position(('data', low-ddy))
        plt1.spines['left'].set_position(('data', xlow-ddx))
        plt.axis([x1[0] - ddx, x1[-1] + ddx, low - ddy, up + ddy])
        plt.show()
        plt.close()
最后调用一下就OK了
def main():
    cat = Miao()

main()

框架大概就是上边这些
flag又又又来了:等有时间就把细节补上
基本能保证通过这玩意儿、可以了解到大部分常用tkinter板块、一部分matplotlib,还有一部分numpy【至少本菜鸡是这样的(T_T)】

下边就先放一点效果图,还有一部分代码图片吧

(代码要把绘图、获取列表放在前头,最后才是ui)

大体框架如下
大体框架
函数字符串图片部分
样本点部分

好的,我可以为您编写一个基于蒙特卡洛方法计算圆周率的程序,并使用 PythontkinterNumPy、SciPy 和 Matplotlib进行可视化设计。以下是程序的代码: ```python import tkinter as tk from tkinter import messagebox import numpy as np from scipy.stats import uniform import matplotlib.pyplot as plt class MonteCarloPi: def __init__(self, master): self.master = master self.master.title("Monte Carlo Pi Calculator") # 创建菜单栏 menubar = tk.Menu(self.master) self.master.config(menu=menubar) # 创建文件菜单 file_menu = tk.Menu(menubar) file_menu.add_command(label="Exit", command=self.quit_program) menubar.add_cascade(label="File", menu=file_menu) # 创建帮助菜单 help_menu = tk.Menu(menubar) help_menu.add_command(label="About", command=self.about) menubar.add_cascade(label="Help", menu=help_menu) # 创建主要的界面元素 tk.Label(self.master, text="Number of Random Points:").grid(row=0, column=0, padx=10, pady=10) self.num_points_entry = tk.Entry(self.master) self.num_points_entry.grid(row=0, column=1) tk.Label(self.master, text="Approximation of Pi:").grid(row=1, column=0, padx=10, pady=10) self.pi_label = tk.Label(self.master, text="") self.pi_label.grid(row=1, column=1) self.calculate_button = tk.Button(self.master, text="Calculate", command=self.calculate_pi) self.calculate_button.grid(row=2, column=0, padx=10, pady=10) self.plot_button = tk.Button(self.master, text="Plot", command=self.plot_results) self.plot_button.grid(row=2, column=1, padx=10, pady=10) def calculate_pi(self): # 获取用户输入的点数 try: num_points = int(self.num_points_entry.get()) if num_points <= 0: raise ValueError except ValueError: messagebox.showerror("Error", "Please enter a positive integer for number of random points.") return # 生成随机点的坐标 x = uniform.rvs(size=num_points) y = uniform.rvs(size=num_points) # 判断每个点是否在圆内 dist = np.sqrt(x**2 + y**2) inside_circle = np.sum(dist < 1) # 计算 pi 的近似值 pi_approx = 4 * inside_circle / num_points # 更新结果标签 self.pi_label.config(text=str(pi_approx)) def plot_results(self): # 获取用户输入的点数 try: num_points = int(self.num_points_entry.get()) if num_points <= 0: raise ValueError except ValueError: messagebox.showerror("Error", "Please enter a positive integer for number of random points.") return # 生成随机点的坐标 x = uniform.rvs(size=num_points) y = uniform.rvs(size=num_points) # 判断每个点是否在圆内 dist = np.sqrt(x**2 + y**2) inside_circle = dist < 1 # 绘制散点图 plt.figure(figsize=(6,6)) plt.scatter(x[inside_circle], y[inside_circle], color="blue", s=10, label="Inside Circle") plt.scatter(x[~inside_circle], y[~inside_circle], color="red", s=10, label="Outside Circle") plt.xlim(0, 1) plt.ylim(0, 1) plt.title("Approximation of Pi: {:.6f}".format(4*np.sum(inside_circle)/num_points)) plt.legend() plt.show() def quit_program(self): self.master.quit() def about(self): messagebox.showinfo("About", "Monte Carlo Pi Calculator\n\nWritten by [Your Name]\nJune 2021") if __name__ == "__main__": root = tk.Tk() app = MonteCarloPi(root) root.mainloop() ``` 这个程序使用 `tkinter` 创建了一个 GUI 界面,包括一个菜单栏、一个用于输入随机点数的文本框、一个计算按钮、一个用于显示圆周率近似值的标签和一个绘制结果的按钮。程序还使用 `NumPy` 和 `SciPy` 生成随机点并计算圆周率,然后使用 `Matplotlib` 绘制散点图并显示圆周率近似值。 您可以运行这个程序,根据提示输入随机点的数量,然后点击计算按钮来计算圆周率近似值。您还可以点击绘制按钮来绘制随机点和圆的散点图,并在图表标题中显示圆周率近似值。在菜单栏中,您可以选择退出程序或查看关于程序的信息。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔的壳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值