强基初中数学&学Python——第三十一课 整式运算模块发布

'''整式加、减、乘、乘方和除以非零有理数运算

 

@作者  码老师

@微信公众号  学思营 ID:xuesying

@公司  深圳五行星软件有限公司

@日期  2020-10-29

 

@使用方法

1、导入模块

>>>from zhengshiyunsuan import *

 

2、单项式

 

 

整数单项式例如:

>>>Mn(3)

 

分数单项式例1:

>>>Mn("1/2")

 

分数单项式例2:

>>>from fractions import Fraction

>>>Mn(Fraction(1, 2))

 

小数单项式(字符串输入,系统自动转为分数):

>>>Mn("3.14")

 

如果单项式有代数,字母和指数作为元组列举在常数之后,例如

>>>Mn("3.14", (x, 2), (y, 2))

注意:指数一定是正整数,如果是1次方,可以省略,例如

>>>Mn("3.14", (x), (y))

 

3、多项式

 

空多项式:

>>>pn = Pn()

>>>pn.pt()

 

可以有列表化单项式,单项式和多项式参数,例如:

>>>m1 = Mn("3.14", (x, 2), (y, 2))

>>>p1 = Pn([12, (x, 3), (y, 3)])

>>>_test = Pn(m1, p1, Mn("2/3", (z)), Pn(m1, [9, (y, 2), (z, 2)]), ["5/3", (z)])

>>>_test.pt()

 

4、加多项式:

>>>_test.add(["2.5", (x,3)], Pn(["7.5", (x,3)])).pt()

 

5、减多项式:

'>>>_test.sub(Pn(["3/2",(z),(x)], ["3/4",(x),(z)])).pt()

 

6、乘多项式:

>>>_test.mul([1,(x)],[1]).pt()

 

7、除以常数:

>>>_test.div("-1/2").pt()

 

8、乘方:")    

>>>Pn([1,(x)],[1,(y)]).pow(5).pt()

 

 

'''

 

from fractions import Fraction

 

class _Power:

    '''乘方和幂'''

    

    #底数,单字母

    baseNumber = None

 

    #指数,正整数

    exponent = 1

 

    #克隆

    def clone(self):

        return _Power(self.baseNumber, self.exponent)

 

    #字母比较

    def cmp(power, otherPower, isDifferent=True):

        a = power.baseNumber

        b = otherPower.baseNumber

        if a > b:

            return 1

        elif a < b:

            return -1

        else:

            if isDifferent:

                return otherPower.exponent-power.exponent  #字母相同,指数大的排前

            else:

                return 0   #用于同一个单项式里合并同字母幂

 

    #打印

    def __str__(self):

        if self.baseNumber == None:

            return ""

        else:

            if self.exponent > 1:

                return "(%s%d)" % (self.baseNumber, self.exponent)

            else:

                return self.baseNumber

 

    #构造方法

    def __init__(self, baseNumber, exponent=1):

        if baseNumber == None or exponent == None:

            raise ValueError("底数和指数不能为空!")

        if not isinstance(exponent, (int)) or exponent < 1:

            raise ValueError("指数只能是正整数!")

        self.baseNumber = baseNumber

        self.exponent = exponent

 

class Mn:

    '''单项式Monomial'''

 

    #系数,非零有理数(分数)

    coefficient = None

 

    #代数,Power的列表

    powers = None

 

    #相反数

    def opp(self):

        if self.coefficient != None:

           self.coefficient = -self.coefficient

        return self

 

    #克隆

    def clone(self):

        m = Mn(self.coefficient)

        if self.powers != None and len(self.powers) > 0:

            m.powers = []

            for power in self.powers:

                m.powers.append(power.clone())

        return m

 

    #单项式次数

    def degreeOfAMonomial(self):

        t = 0

        if self.powers != None and len(self.powers) > 0:

            for power in self.powers:

                t += power.exponent

        return t

 

    #比较大小:幂阶降序,字母升序。

    #第二个要在前正值;合并0;其它负值

    def cmp(monomial, otherMonomial):       

        d1 = monomial.degreeOfAMonomial()

        d2 = otherMonomial.degreeOfAMonomial()

        if d1 != d2:

            return d2 - d1   #如果d2>d1 d2-d1>0要把第二个插入第一个的位置

        else:

            if d1 == 0:

                return 0  #两个都是常数项

            len1= len(monomial.powers) #第一个元数

            len2= len(otherMonomial.powers) #第二个元数

            maxLen = max(len1, len2)

            for i in range(maxLen):

                t =  monomial.powers[i].cmp(otherMonomial.powers[i])

                if t != 0:

                    return t   #第二个在后的话t>0,需要插入

            if len1 != len2:

                return len2 - len1  #如果len2>len1,则len2-len1>0,则第二个要插入第一个的位置

 

            return 0   #同类项

            

 

 

    #按底的字母顺序排序,同底指数合并

    def _sort1(powers, idx, num):

        power = powers[num]

        for i in range(idx+1):

            m = powers[i]

            t = m.cmp(power, False)

            if t == 0:                              #合并同类项

                m.exponent += power.exponent

                return idx

            elif t >0:                              #新的高阶项,高阶项插入当前位置

                idx += 1

                for p in range(idx, i, -1):         #后推其它项

                    powers[p] = powers[p-1]

                powers[i] = power                     #插入该项

                return idx                          #返回结果数

        idx += 1

        powers[idx] = power                           #把新项插在结果最后

        return idx

    

    def _sort(powers):

        idx = 0   #结果下标

        lth = len(powers)

        for num in range(1, lth):

            idx = Mn._sort1(powers, idx, num)  #排序和合并1项

        idx += 1

        if idx < lth:

            del(powers[idx:])

        for power in powers:

            if power.exponent == 0:   #去除字母是0的元

                del(power)

        return powers;

 

    #单项式相乘

    def mul(first, second):

        first.coefficient *= second.coefficient

        if first.powers == None or len(first.powers) == 0:

            first.powers = second.powers

        elif second.powers != None and len(second.powers) >0:

            first.powers.extend(second.powers)

            first.powers = Mn._sort(first.powers)

        return first

        

 

    #打印

    def print(self, isFirst):

        if self.coefficient == None or self.coefficient == 0:

            return ""

        else:

            if self.coefficient == 1:

                s = ""

            elif self.coefficient == -1:

                s = "-"

            else:

                s = str(self.coefficient)

            if self.coefficient > 0:

                if not isFirst:

                    s = "+" + s

            if self.powers != None and len(self.powers) > 0:  #非常数项

                for power in self.powers:

                    s += str(power)

            return s

 

    #打印

    def __str__(self):

         return self.print(False)

            

 

    #构造方法

    def __init__(self, coefficient, *powers):

        if coefficient == None:  #空单项式,与0相同

            return

        if not isinstance(coefficient, (int, Fraction, str)):

            raise ValueError("单项式系数只能是整数、分数(Fraction)或字符串(小数和分数)")

        self.coefficient = Fraction(coefficient)

        if self.coefficient != 0:          

            if powers != None and len(powers) > 0:

                prs = []

                for power in powers:

                    prs.append(_Power(*power)) #参数解包

                self.powers = Mn._sort(prs)

 

class Pn:

    '''多项式Polynomial'''

 

    #项Monomial列表

    terms = None

 

    #克隆

    def _clone(self):

        p = Pn()

        if self.terms == None or len(self.terms) == 0:

            return p

        lth = len(self.terms)

        t = []

        for i in range(lth):

            t.append(self.terms[i].clone())

        p.terms = t

        return p

 

    #合并同类项与排序

    def _sort1(terms, idx, num):

        term = terms[num]  #需检查的元素

        for i in range(idx+1):  #把元素插入或合并到结果中

            m = terms[i]

            t = m.cmp(term)     #比较

            if t == 0:                              #合并同类项

                m.coefficient += term.coefficient                 

                return idx

            elif t > 0:                              #新的高阶项,高阶项插入当前位置

                idx += 1

                for p in range(idx, i, -1):         #后推其它项

                    terms[p] = terms[p-1]

                terms[i] = term                     #插入该项

                return idx                          #返回结果数

        idx += 1

        terms[idx] = term                           #把新项插在结果最后

        return idx

            

 

    #合并同类项与排序

    def _sort(terms):

        idx = 0   #结果下标

        lth = len(terms)

        for num in range(1, lth):

            idx = Pn._sort1(terms, idx, num)  #排序和合并1项

            #print("idx=%d" % idx)

        #消除0系数项

        temp = []

        for num in range(idx +1):

            term = terms[num]

            if term.coefficient != 0:

                temp.append(term)

        nlth = len(temp)

        if nlth == 0:

            del(terms[0:])

            return terms

        else:

            for num in range(nlth):

                terms[num] = temp[num]

            if nlth < lth:

                del(terms[nlth:])

            return terms;

 

 

    #加

    def _add(self, isSub, *terms):

        if terms != None and len(terms) > 0:

            if self.terms == None:

                self.terms = []

            for term in terms:

                if isinstance(term, Pn):

                    if term.terms != None and len(term.terms) > 0:

                        for t in term.terms:

                            if isSub:

                                self.terms.append(t.clone().opp())  #克隆,保证原式不受影响

                            else:

                                self.terms.append(t.clone())  

                else:

                    if isinstance(term, Mn):

                        if isSub:

                            self.terms.append(term.clone().opp())     #克隆防止影响原对象

                        else:

                            self.terms.append(term.clone())     

                    else:

                        if isSub:

                            self.terms.append(Mn(*term).opp())  #解包list添加1个单项式,无需克隆

                        else:

                            self.terms.append(Mn(*term))  

            Pn._sort(self.terms) #排序

            

    def add(self, *terms):

        s = self._clone()  #克隆防止改变原对象

        s._add(False, *terms)

        return s

 

    #减            

    def sub(self, *terms):

        s = self._clone()  #克隆防止改变原对象

        s._add(True, *terms)

        return s

   

        

    #乘除常数,私有方法不克隆

    def _muldiv(self, fraction, isdiv):

        if self.terms != None and len(self.terms) >0:

            try:

                p = Fraction(fraction)

                for term in self.terms:

                    if isdiv:

                        term.coefficient /= p

                    else:

                        term.coefficient *= p

            except Exception as e:

                print(e)

        return self

 

 

 

    #多项式乘单项式,私有方法都不可以克隆

    def _mul(pn, mn):

        for term in pn.terms:

            term.mul(mn)

        return pn

 

    #乘

    def mul(self, *terms):

        if terms == None or len(terms) == 0:  #空调用返回自己

            return self

        if len(terms) == 1 and isinstance(terms[0],(int, str)): #乘一个有理数

            return self._clone()._muldiv(terms[0], False)      #需要克隆对象

        p = Pn(*terms)  #建立要乘的多项式 如果里面有Mn或Pn,则它们会被克隆

        if self.terms == None or len(self.terms) == 0: #self是空多项式可忽略

            return p

        elif p.terms != None and len(p.terms) >0:

            lth = len(p.terms)

            s = self._clone()._mul(p.terms[0])  #乘单项式

            if lth == 1:                             

                return s

            for i in range(lth-1):  #克隆对象乘

                s._add(False, self._clone()._mul(p.terms[i+1]))

            return s

        else:                       #p为空多项式

            return self;

 

            

    #乘方

    def pow(self, num):

        if not isinstance(num, (int)) or num < 2:

            print("请输入大于1的整数")

            return self

        if self.terms == None or len(self.terms) == 0:

            return self

        s = self._clone()

        for i in range(num-1):

            s = s.mul(self)  # 由于mul会克隆,这里不用克隆

        return s

 

 

    #除

    def div(self, fraction):

        return self._clone()._muldiv(fraction, True)

 

    #print用

    def __str__(self):

        s = "原式="

        if self.terms == None or len(self.terms) == 0:

            s += "0"

        else:

            s += self.terms[0].print(True)

            for i in range(1, len(self.terms)):

                s += self.terms[i].print(False)

        return s

 

    #打印出多项式

    def pt(self):

        print(self)

 

 

    #构造方法

    def __init__(self, *terms):

        self._add(False, *terms)

 

#定义字母

A = "A"

B = "B"

C = "C"

D = "D"

E = "E"

F = "F"

G = "G"

H = "H"

I = "I"

J = "J"

K = "K"

L = "L"

M = "M"

N = "N"

O = "O"

P = "P"

Q = "Q"

R = "R"

S = "S"

T = "T"

U = "U"

V = "V"

W = "W"

X = "X"

Y = "Y"

Z = "Z"

a = "a"

b = "b"

c = "c"

d = "d"

e = "e"

f = "f"

g = "g"

h = "h"

i = "i"

j = "j"

k = "k"

l = "l"

m = "m"

n = "n"

o = "o"

p = "p"

q = "q"

r = "r"

s = "s"

t = "t"

u = "u"

v = "v"

w = "w"

x = "x"

y = "y"

z = "z"

 

 

if __name__ == "__main__":

 

    print("\n多项式测试:")

    print("\n导入整式运行模块:")

    print('>>>from zhengshiyunsuan import *')

    print("\n构造函数测试:")

    print('>>>_mn = Mn("3/2", (x, 2))')

    print('>>>_pn = Pn(["3/5", (z, 2)])')

    print('>>>_test = Pn(["-3.14", (z, 2)], _mn, _pn, [4])')

    print('>>>_test.pt()')

    _mn = Mn("3/2", (x, 2))

    _pn = Pn(["3/5", (z, 2)])

    _test = Pn(["-3.14", (z, 2)], _mn, _pn, [4])

    _test.pt()

    print("对比")

    print('>>>_test = Pn(["-3.14", (z, 2)], ["3/2", (x, 2)], ["3/5", (z, 2)], [4])')

    print('>>>_test.pt()')

    _test = Pn(["-3.14", (z, 2)], ["3/2", (x, 2)], ["3/5", (z, 2)], [4])

    _test.pt()

    print("\n减多项式测试:")

    print('>>>_test.sub(Pn(["3/2",(z),(x)], ["3/4",(x),(z)])).pt()')

    _test.sub(Pn(["3/2",(z),(x)], ["3/4",(x),(z)])).pt()

    print("\n加多项式测试:")

    print('>>>_test.add(["2.5", (x,3)], Pn(["7.5", (x,3)])).pt()')

    _test.add(["2.5", (x,3)], Pn(["7.5", (x,3)])).pt()

    print("\n乘多项式测试:")

    print('>>>_test.mul([1,(x)],[1]).pt()')

    _test.mul([1,(x)],[1]).pt()    

    print("\n多项式除常数测试:")

    print('>>>_test.div("-1/2").pt() ')    

    _test.div("-1/2").pt()

    print("\n多项式乘方测试:")    

    print('>>>Pn([1,(x)],[1,(y)]).pow(5).pt()')

    Pn([1,(x)],[1,(y)]).pow(5).pt()

    print("\n多项式乘方测试杨辉三角:")

    print('>>>_t = Pn([1,(x)],[1,(y)])')

    print('>>>for _i in range(11):')

    print('...    _t.pow(_i).pt()')

    _t = Pn([1,(x)],[1,(y)])

    for _i in range(11):

        _t.pow(_i).pt()