自定义解多元多次方程(变量参数名称及数量不限,方程数量不限)模块,计算公式模块,常用的形状体积、面积计算模块

最近根据PYTHON可以支持变量名可以动态的指定,结合PYTHON 的sympy符号计算库,编写了这个可以计算求解任何方程的模块函数,用法详示例,没有测试更多的方程组,随手编了两个三元二次方程组(三个未知量,三个方程,最高幂2),均得到了正确的解。

测试用主窗体的代码如下:

#文件模块名称:mathEx_Text.py
#用于测试数学计算模块mathEx.py的PYQT窗体
import os,sys       #导入系统模块
import time
import math
import copy 
import random
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtCore
from PyQt5.QtGui import QMovie
from PyQt5.QtCore import QByteArray

from mathEx   import *                #导入自定义的要测试的mathEx.py模块
##################################################################
#测试数学计算类的主窗体
class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('测试mathEx类:扩展数学计算库')
        self.setGeometry(0, 0, 1600, 600)
        self.statusbar = self.statusBar()
        self.statusbar.showMessage('准备')
        self.setStatusTip('准备...')  
        self.qimage = QImage('1.jpg')   #底图
        self.initUI()
    def initUI(self):
       
        self.btn_Test1=QPushButton('1测试代码1',self)
        self.btn_Test1.setGeometry(1450,50,150,50)
        self.btn_Test1.clicked.connect(self.test1)
        self.btn_Test2=QPushButton('2测试代码',self)
        self.btn_Test2.setGeometry(1450,150,150,50)
        self.btn_Test2.clicked.connect(self.test2)
        self.btn_Test3=QPushButton('3测试代码',self)
        self.btn_Test3.setGeometry(1450,250,150,50)
        self.btn_Test3.clicked.connect(self.test3)

        self.Lab01=QLabel(self)
        self.Lab01.setGeometry(50,50,200,200)
        self.Lab01.setText('测试标签1')
        #self.Lab01.raise_()

        self.Lab02=QLabel(self)
        self.Lab02.setGeometry(50,300,200,200)
        self.Lab02.setText('测试标签2')

########################################################################################
    def test1(self):   
        m=mathEx()
        countxt='1+2*sin(sqrt(30*pi/180))'
        value=m.countText(countxt)
        print(f'计算公式的值{countxt}={value}')   


    def test2(self):   
        m=mathEx()
        vars1='x,y,z'                            #此字符串中的变量名称数量及形式要出下面的方程中保持一致
        lsteqs1=['x**2+y**2-z**2',              #方程1:此方程中的变量名称要同vars相一致:本例用的股定律,勾3股4弦5,计划x=3,y=4,c=5看还有其也解没有
              'x+y+z-12',                       #方程2:此方程中的变量名称要同vars相一致
              'cos(atan(x/y))-4/5'              #方程3:此方程中的变量名称要同vars相一致
              #'方程n..........'                #.方程n.......此方程中的变量名称要同vars相一致,没测试过最大支持的变更和方程数及计算用时,和是否存在BUG
              ]
        vars2='AB,B,C'                              #此字符串中的变量名称数量及形式(可为多字符)要出下面的方程中保持一致
        lsteqs2=['2*AB**2+3*B**2-15*AB-653',        #方程1:此方程中的变量名称要同vars相一致
              '5*AB**2+4*B**2-15*B-826.25',         #方程2:此方程中的变量名称要同vars相一致
              '2*AB + 3*B + C - 54'                 #方程3:此方程中的变量名称要同vars相一致
              #'方程n..........'                    #.方程n.......此方程中的变量名称要同vars相一致,没测试过最大支持的变更和方程数及计算用时,和是否存在BUG
              ]
   
        m.count_XYZ(vars1,lsteqs1)  #解方程组1
        m.count_XYZ(vars2,lsteqs2)  #解方程组2

    def test3(self):   
          m=mathEx()
          v=m.round(m.V_cone(5),3)   #保留3位小数
          print(f'半径5球体积={v}')
########################################################################################
if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyWidget()
    w.show()
    sys.exit(app.exec())

以下为我自己编写的数学计算模块mathEx.py,没有严格作详细测试,只是供大家共同学习提高。

#mathEx.py:定义数学计算扩展库
#包括可解多元多次方程,常用的面积、体积等计算函数等,扩展中.......
import os,sys       
import time
from  math import *
import copy 
import random
import pickle   #支持保存和导入字典数据的模块(PICKLE方式:仅PTHON支持),为默认,可以保存和加载不受限制的任意数据
import json     #支持保存和导入字典数据的模块(JSON方式:多种语言支持)
import csv      #支持保存和导入字典数据的模块(CSV方式:多种语言支持)
import numpy as np    
from scipy.optimize import fsolve
#import pandas as pd 
from sympy import symbols, solve    #符号计算模块
from sympy import sympify


_DEBUG_ = True #为True时,终端会输出参数帮助信息
#if _DEBUG_:print(f'\n帮助信息:调用的函数:,参数信息:参数示例:')
#定义将的所有程序#要用到各种资源文件预加载到内存中,使用时从此内存中的数据直接使用
class mathEx():
    #以下定义常用数学计算常数

    def __init__(self):
        self.about='本类为自定义的一些常用到的数学计算公式'
    #######################################################################3

    def insertchar(self,original_str, char_to_insert, index):
        # 在索引位置前插入字符,并返回新字符串
        return original_str[:index] + char_to_insert + original_str[index:]
    
    #以下为自定义的数学计算函数
    #1、将可识别的计算公式返回计算结果
    #参数:计算公式,示列:'1+2*math.sin(30*pi/180)' , 参数bAddMath=true时,将对计算文本进行处理,将math中的函数前加上前缀math.字符
    def countText(self,formula,bAddMath=False):
        #if _DEBUG_:print(f'\n帮助信息:调用的函数:countTxt(self,formula,bAddMath=False),参数信息:formula=计算公式字符串,bAddMath=是否为函数名前增加math.前缀参数示例:"2345+2*sin(30*PI/180)"')
        try:
            #先对计算公式中进行容错处理,如使用了math中的函数,如函数名前没有使用math.,应补上这几个字符串
            countStr=formula
            if(bAddMath):  #如果要对计算字串进行二次处理
                addstr='math.'
                pos=0
                addn=0
                count=len(formula)
                while pos<count-1:
                    c=formula[pos]
                    if((pos==0) or (c=='+' or c=='-' or c=='*' or c=='\\' or c=='(' )):
                        if(pos<count-9):
                            bk5str=formula[pos+1:pos+6]
                            bk7str=formula[pos+1:pos+8]
                            if(bk5str !='math.' and bk7str !='mathEx.' and formula[pos+1].isalpha()):
                                if(pos==0):
                                    countStr=self.insertchar(countStr,addstr,0)
                                    addn+=1
                                else:
                                    countStr=self.insertchar(countStr,addstr,pos+1+addn*5)
                                    addn+=1
                        else:
                            if(formula[pos+1].isalpha()):
                                    countStr=self.insertchar(countStr,addstr,pos+1+addn*5)
                                    addn+=1
                    pos+=1
                print(f'计算式加工后的公式={countStr}')
            value = eval(countStr)
            return value
        except Exception as e:  # 如果发生异常,执行这里的代码
            print(f'要计算的公式不正确请检查公式:{countStr}')
            return None
    #2、返回指小数点位数的字符串
    #参数:        浮点数  指定的小数位
    def round(self,fvalue,pointNum=3):
        value = round(fvalue, pointNum)
        return value
    #3、向下取整,
    def roundDown(self,fvalue):
        return floor(fvalue)
    #4、向上取整
    def roundUp(self,fvalue):
        return ceil(fvalue)
    #5、度数转弧度
    #参数:          十进制度数
    def DegToRad(self,deg):
        return deg*pi/180.0
    #6、弧度转度数
    #参数:          弧度数
    def RadToDeg(self,rad):
        return rad*180.0/pi
    
    #7、解多元多次方程
    #参数svar=''=> 要计算的变量名称,变量间用,分开
    #参数lstSeqs=['方程1','方程2',........]=>方程等式列表,常规变量有几个,方程就该有几个,方程等式应将等号右侧的项全部移到左侧后再列入方程字串中
    #如方程1:2*x**2+3*y+50=10*x+5,则列入方程1的字串为:2*x**2+3*y+50-(10*x+5)
    def count_XYZ(self,svar,lstSeqs):
        timestart=time.time()
        lstVars=svar.split(',')
        lstVarName=[]
        lstStrName=[]
        index=0
        for varName in lstVars :      #将方程变量字符串(建议用单字符如X  Y  z等)转换成代码可识别的变量名
            lstVarName.append(varName)
            lstStrName.append(varName)
            globals()[lstVarName[index]]=varName   #注,此代码后lstVarName[index]变量就是变量名了,不是值了,要用值,用列表变量lstStrName
            index+=1

        # 动态定义变量:加了注释的已被下面的动态语名替换,供参考原理
        #x, y, z = symbols('x y z')
        index = 0
        count=len(lstVarName)
        while index < count:
            lstVarName[index]=symbols(lstStrName[index])
            index+=1

        lsteq=[]
        for oneeq in lstSeqs:
            eq=sympify(oneeq)   #各个字符串方程转换成代码公式
            lsteq.append(eq)

        #sol = solve([eq1, eq2, eq3], [x, y, z]) # 求解方程组的计算公式
        sol = solve(lsteq,lstVarName) # 求解方程组的计算公式:按上行例名变换成动态

        sequNum=len(sol)  #方程解的数量
        if(sequNum==0):
            print('本方程没有得到任何解,无计算值结果')
            return None
        index=1
        for sequs in sol:
            svalue=str(sequs)
            print(f'\n方程第{index}组解是(可能是计算公式):\n{svalue}')
            lstxyz = svalue.split(',')
            n=0
            chgSxyz=''
            for sxyz in lstxyz:
                count=len(sxyz)
                if(count>0):
                    c1=sxyz[0]
                    c2=sxyz[count-1]
                    if(c1=='('):
                       chgSxyz=sxyz[1:count]
                    if(c2==')'):
                       chgSxyz=sxyz[0:count-1]
                    lstxyz[n]=copy.deepcopy(chgSxyz)
                n+=1
            #输出方程解的值
            id=0
            for xyz in lstxyz:
                if(xyz.find('I')>0):  #解是复数时
                     print(f'方程第{index}组解:方程变量{lstStrName[id]}复数值={xyz}')  #对复数输出复数的值
                elif(not isinstance(xyz, (int, float))):      #解中包含公式还不是最终的值时
                    lstVarName[id]=self.countText(xyz)   #对非复数值依次计算每个变量的值
                    print(f'方程第{index}组解:方程变量{lstStrName[id]}={lstVarName[id]}')
                else:   #方程的解已经是数字了,不需要再经过countText()来计算一道公式
                    print(f'方程第{index}组解:方程变量{lstStrName[id]}={lstVarName[id]}')
                id+=1
            index+=1

        timeend=time.time()
        print(f'\n本次计算共用时:{self.round(timeend-timestart,3)}秒')
        return  lstxyz


    #7、计算椭圆面积
    #参数:               长半轴长  短半轴长
    def S_elliptic(self,longHelf,sortHelf):
         return pi*longHelf*sortHelf
    #8、计算扇形面积
    #参数:半径或直径,扇形中心角角度(若是弧度要换算)
    def S_sector(self,a,deg,rD='R'):
         rD=rD.upper()  
         if rD=='D':a=a/2
         return pi*a**2*deg/360

    #9、计算扇形弦长和弦高
    #参数:半径或直径,扇形中心角角度(若是弧度要换算)
    def L_sector(self,a,deg,rD='R'):
        rD=rD.upper()  
        if rD=='D':a=a/2
        L= 2*a*sin(self.DegToRad(deg)/2)
        h=a*cos(self.DegToRad(deg)/2)
        return L,h
    
    #10、计算三角形面积(已知两边夹一角)
    #参数:两个边长加一角度(角度单位)
    def S_triangle_ab_degC(self,a,b,degC):
        return 0.5*a*b*sin(self.DegToRad(degC))
    
    #11、计算三角形面积(已知三条边长)
    #参数:三个边长
    def S_triangle_abc(self,a,b,c):
        p=(a+b+c)/2
        return sqrt(p*(p-a)*(p-b)*(p-c))
    
    #12、计算棱形面积(deg=0:已知两对角线长,deg>0:参数表示角度两侧的棱形边长)
    #参数:对角线长(deg=0时),或棱形边长(deg>0时),
    def S_cuboid_diag(self,a,b,deg=0):
        if(deg==0):return a*b/2
        else:
            c=(a**2+b**2-2*a*b*cos(self.DegToRad(deg)))
            d=(a**2+b**2-2*a*b*cos(pi/180-self.DegToRad(deg)))
            return c*d/2

    #13、计算三角形角度(已知三边,返回三个角度:弧度)
    #参数:三个边长
    def A_triangle_abc(self,a,b,c):
        radA=acos((b**2+c**2-a**2)/(2*b*c))
        radB=acos((a**2+c**2-b**2)/(2*a*c))
        radC=acos((a**2+b**2-c**2)/(2*a*b))
        return radA,radB,radC
    
    #14、计算三角形第三条边长(已知夹一角度:角度)
    #参数:a边长,b边长,ab夹角度
    def A_triangle_ab_degC(self,a,b,degC):
        return sqrt(a**2+b**2-2*a*b*cos(self.DegToRad(degC)))
    
    #15、计算三角形第三条边长(两条边及两条边所对角的角度)
    #参数:a边长,a边对角度,b边长,b边对角度
    def A_triangle_ab_degC(self,a,degA,b,degB):
        radC=self.DegToRad(180)-self.DegToRad(degA)-self.DegToRad(degB)
        c=a/sin(self.DegToRad(degA))*sin(radC)
        return c
    
    #16、计算圆台体积
    #参数:大半径或直径,小半径或直径,高度
    def V_frustum(self,a,b,h,rD='R'):
        rD=rD.upper()  
        if rD=='D':
            a=a/2 
            b=b/2
        return pi*h*(a**2+b**2+a*b)/3
    
    #17、计算圆台表面积
    #参数:大半径或直径,小半径或直径,高度,传入的参数是半径还是直径,面积是否包括上顶和下底面
    def S_frustum(self,a,b,h,rD='R',inAllS=True):
        rD=rD.upper()  
        if rD=='D':
            a=a/2 
            b=b/2
        S = pi*((a+b)*sqrt(a**2+b**2+h**2))
        if(inAllS): S=S+pi*(a**2+b**2)
        return S
    
    #18、计算圆柱体积
    #参数:半径或直径,高度
    def V_cylinder(self,a,h,rD='R'):
        rD=rD.upper()  
        if rD=='D':
            a=a/2 
        return pi*a**2*h
    
    #19、计算圆柱表面积
    #参数:半径或直径,高度
    def S_cylinder(self,a,b,h,rD='R',inAllS=True):
        rD=rD.upper()  
        if rD=='D':
            a=a/2 
        S = 2*pi*a*h
        if(inAllS): S=S+2*pi*a**2
        return S
     #20、计算圆锥体积
    #参数:小半径或直径,高度
    def V_cone(self,a,h,rD='R'):
        rD=rD.upper()  
        if rD=='D': a=a/2
        return pi*h*(a**2)/3
    
    #21、计算圆锥表面积
    #参数:半径或直径,高度
    def S_cone(self,a,h,rD='R',inAllS=True):
        rD=rD.upper()  
        if rD=='D': a=a/2
        L=sqrt(h**2+a**2)
        S= pi*a*(L)
        if(inAllS): S=S+pi*a**2
        return S
    #22、计算球体积
    #参数:球半径或直径
    def V_cone(self,a,rD='R'):
        rD=rD.upper()  
        if rD=='D': a=a/2
        return pi*a*a*a*4/3
    
    #23、计算球表面积
    #参数:球半径或直径
    def S_cone(self,a,rD='R'):
        rD=rD.upper()  
        if rD=='D': a=a/2
        return 4*pi*a*a
    #24、计算球冠体积
    #参数:球半径或直径,冠高
    def V_crown(self,a,h,rD='R'):
        rD=rD.upper()  
        if rD=='D': a=a/2
        return (pi/3)*(3*a-h)*h**2
    #25、计算球冠表面积
    #参数:球半径或直径,b球缺半径,冠高
    def S_crown(self,a,b,h,rD='R',inAllS=True):
        rD=rD.upper()  
        if rD=='D': a=a/2
        S=2*pi*a*h
        if(inAllS): S=S+pi*b**2
        return S
    #26、计算圆环体积
    #参数:环回转半径或直径,环断面半径或直径
    def V_segment(self,a,b,rD='R'):
        rD=rD.upper()  
        if rD=='D': 
            a=a/2
            b=b/2
        return 2*pi*a*pi*b**2
    #27、计算圆环表面积
    #参数:环回转半径或直径,环断面半径或直径
    def S_segment(self,a,b,rD='R'):
        rD=rD.upper()  
        if rD=='D': 
            a=a/2
            b=b/2
        return 2*pi*a*2*pi*b



#######################################################################3
#以下为工程类用计算
#计算两点间的距离(平面时,参数不必传入z1和z2,3D时要传入z1和z2的值)
def L_towPoint(self,x1,y1,x2,y2,z1=0,z2=0):
    return sqrt((x2-x1)**2+(y2-y1)**2+(z2-z1)**2)

#计算一直线段中间某一点的高程
#参数:起点到中间点的距离,中间到到终点的距离,起点的高程,终点的高程
def Z_lineTreePoint(L1,L2,z1,z2):
    Zx=None
    if(z1<=z2):
        Zx=z1+L1/(L1+L2)*(z2-z1)
    else:
        Zx=z2+L2/(L1+L2)*(z1-z2)
    return Zx

#计算两点中间某一点的坐标
#参数:起点坐标X1,起点坐标Y1,终点的坐标x2, 终点坐标y2,起点到计算点的距离
def Z_lineTreePoint_XYZ(x1,y1,x2,y2,L1):
    pass 





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

mr_LuoWei2009

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

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

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

打赏作者

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

抵扣说明:

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

余额充值