猫史档案馆


更好的数学(大坑)

用户:红石小蝈红石小蝈查看:1 回复:2 评论:1 创建时间:2019-05-17T21:57:57


共计5个类,(1个成品,4个坑)咕咕咕

import turtle
from math import *
from turtle import Vec2D  #This will stay here until I have a vec class

import fourier  ###gonna be moved in###


####helpers function & constants####
def longer(a,b):
    if len(a)>len(b):
        return a
    elif len(a)<len(b):
        return b
    else:
        #print('same lenth')
        return a,b
def n_to_s(x):
    if float(x)>=0:
        return '+'+str(x)
    else :
        return str(x)
def tp(p,pos_x,pos_y):
    p.pu()
    p.goto(float(pos_x), float(pos_y))
    p.pd()
DEFAULT_COLOR='#66ccff'
AUTHERS_SPACE='https://space.bilibili.com/352143698'
DEFAULT_PEN=None
DRAW_WHEN_REPR=True
def do_drawing():
    '''do this before u draw sth'''
    global DEFAULT_PEN
    DEFAULT_PEN=turtle.Turtle()
    DEFAULT_PEN.speed(0)
if __name__=='__main__':
    do_drawing()
####math constants####
M=2.302585092994046
number_types=['Rational','int','float']
func_types=['Po_func']
tri=[sin,cos,tan]
####math funcs & classes####
def Re(z):
    '''return the real part of z'''
    return z.real
def Im(z):
    '''return the imaginary part of z'''
    return z.imag
def Arg(z):
    '''return the principle argument  '主幅角'
    of a complex number'''
    return atan2(Im(z),Re(z))
def vec(z):return Vec2D(Re(z),Im(z))
def cot(theta):
    '''return the cotangent of theta'''
    return tan(theta-pi/2)

class Rational:
    '''a rational number class instead of
    python integer or floating numbers, the
    base of rational functions'''
    def __init__(self,num=0,den=1):
        if den == 0:
            raise ZeroDivisionError('the denominator can\'t be zero')
        elif not isinstance(num,(int,float)) and isinstance(den,(int,float)):
            raise TypeError('the numrator and the denominator can only be numbers')
        if den == 1 and isinstance(num,float):
            raise NotImplementedError('''you still can't change floating numbers into
                Rationals,if u have questions please go to'''+AUTHERS_SPACE+'for help')
        else:
            self.num=num
            self.den=den
    def reduct(self):
        '''make the fraction in the lowest term'''
        num=int(self.num/gcd(self.num,self.den))
        den=int(self.den/gcd(self.num,self.den))
        self.num=num
        self.den=den
    ##change rationals into integers and floating numbers
    def __int__(self):
        return self.num//self.den
    def __float__(self):
        return self.num/self.den
    ##comparing rationals with others numbers
    def __eq__(self,other):
        return float(self)==float(other)
    def __ge__(self,other):
        return float(self)>=float(other)
    def __gt__(self,other):
        return float(self)>float(other)
    def __le__(self,other):
        return float(self)<=float(other)
    def __lt__(self,other):
        return float(self)<float(other)
    def __ne__(self,other):
        return float(self)!=float(other)
    ##compute rationals with numbers
    def __add__(self,other):
        if isinstance(other,(int,Po_func)):
            return Rational(self.num+other*self.den,self.den)
        elif isinstance(other,Rational) :
            d=self.den*other.den
            n=self.den*other.num+self.num*other.den
            a=Rational(d,n)
            a.reduct()
            return a
    def __neg__(self):
        return Rational(-self.num,self.den)
    def __sub__(self,other):
        return self+(-other)
    def __rsub__(self,other):
        return -(self-other)
    def __mul__(self,other):
        if isinstance(other,int):
            a=Rational(self.num*other,self.den)
            a.reduct()
            return a
        elif isinstance(other,Rational):
            a=Rational(self.num*other.num,self.den*other.den)
            a.reduct()
            return a
    def __div__(self,other):
        if float(other)==0:
            raise ZeroDivisionError('Can\'t divide by zero')
        if isinstance(other,int):
            a = Rational(self.num,self.den*other)
            a.reduct()
            return a
        elif isinstance(other,Rational) :
            a = Rational(self.num*other.den,self.den*other.num)
            a.reduct()
            return a
    def __rdiv__(self,other):
        if self==0:
            raise ZeroDivisionError('Can\'t divide by zero')
        a = Rational(self.den*other,self.num)
        a.reduct()
        return a
    def __pow__(self,other):
        if other>=0:
            return Rational(self.num**other,self.den**other)
        if other<0:
            return Rational(self.den**(-other),self.num**(-other))
    __rmul__=__mul__
    __radd__=__add__
    ##show rationals
    def __repr__(self):
        if self.den==1:
            return str(self.num)
        return '('+str(self.num)+'/'+str(self.den)+')'

class Interval:
    '''mathmatical single interval class
    in python, base of lots of things
    e.g.:(i0,i1 are two intervals)
    i0+i1           : i0∪i1
    i0.contain(i1)  : i1⊆i0
    i0.include(num) : num∈i0
    '''
    def __init__(self,l_bound=-inf,r_bound=inf,l_open=True,r_open=True):
        if (isinstance(l_bound,(int,float,Rational))
            and isinstance(r_bound,(int,float,Rational))):
            if r_bound<l_bound :
                r_bound=l_bound
                if not(l_open or r_open):
                    l_open=r_open=False
            self.l_bound=l_bound
            self.r_bound=r_bound
            self.l_open=l_open
            self.r_open=r_open
        #elif isinstance(l_bound,str):self=Interval.fromstr(l_bound)
        else:
            raise TypeError('the bounds can only be numbers')

    @clas喵ethod
    def fromstr(cls,i):
        if not isinstance(i,str):
            raise TypeError
        l_open= i[0]=='('
        r_open= i[-1]==')'
        a,b = i[1:-1].split(',')
        l_bound=float(a)
        r_bound=float(b)
        i=cls(l_bound,r_bound,l_open,r_open)
        return i

    ###compare Intervals
    def __eq__(self, other):
        return ((self.l_bound==other.l_bound and self.r_bound==other.r_bound)
                and (self.l_open==other.l_open and self.r_open==other.r_open))
    def __ge__(self, other):
        if self.r_open and (not other.r_open):return self.r_bound>other.r_bound
        else:return self.r_bound>=other.r_bound
    def __gt__(self, other):
        if (not self.r_open) and other.r_open:return self.r_bound>=other.r_bound
        else:return self.r_bound>other.r_bound
    def __le__(self, other):
        if self.l_open and (not other.l_open):return self.l_bound<other.l_bound
        else:return self.l_bound<=other.l_bound
    def __lt__(self, other):
        if (not self.l_open) and other.r_open:return self.r_bound>=other.r_bound
        else:return self.r_bound>other.r_bound    
    def __ne__(self, other):
        return not self==other
    
    ###computing Intervals
    def __add__(self,other):
        if isinstance(other,Interval):
            if self>other:_x,_y=self,other
            else:_x,_y=other,self
            if _x.l_open and _y.r_open:_b= _x.l_bound<_y.r_bound
            else: _b= _x.l_bound<=_y.r_bound
            if _b:
                if _x.l_bound<_y.l_bound:return _x
                else:return Interval(_y.l_bound,_x.r_bound,_y.l_open,_x.r_open)
            else:return Compound_Interval(_x,_y) 
        elif isinstance(other,Compound_Interval):
            inters=[self]
            for _x in other.intervals:
                if self.include(_x):#_r = self+_x
                    pass
                elif _x.include(self):
                    return other
                elif isinstance(_x+self,Interval):
                    inters.append(_x+self)
                else:
                    inters.append(_x)
            return Compound_Interval.fromlist(inters)
            #raise NotImplementedError
        else:
            raise TypeError('you can only add intervals to intervals')

    ###main methods of Intervals
    def include(self,num):
        '''return True if num∈interval
        return False otherwise'''
        if self.l_open :b = self.l_bound<num
        else :b = self.l_bound<=num
        if self.r_open:b = b and num<self.r_bound
        else:b = b and num<=self.r_bound
        return b
    def contain(self, other):
        '''return True if other⊆self
        return False otherwise
        '''
        if self.l_open and (not other.l_open):b = self.l_bound<other.l_bound
        else :b = self.l_bound<=other.l_bound
        if self.r_open and (not other.r_open):b = b and other.r_bound<self.r_bound
        else :b = b and other.r_bound<=self.r_bound
        return b
    ##represent method
    def __repr__(self):
        s=''
        if self.l_open :s+='('
        else :s+='['
        s+=str(self.l_bound)+','+str(self.r_bound)
        if self.r_open:s+=')'
        else:s+=']'
        return s
    
    __radd__=__add__

Intvl = Interval
str_to_intvl = Intvl.fromstr
R = Interval()

class Compound_Interval:
    '''the union set of single intervals,
    base of things
    '''
    def __init__(self,*s):
        s=list(s)
        s.sort(reverse=True)
        self.intervals=s

    @clas喵ethod
    def fromlist(cls,l):
        if isinstance(l,list):
            i=cls()
            l.sort(reverse=True)
            i.intervals=l
            return i
        else:
            raise TypeError

    def simplify(self):
        '''simplify the set,not implemented'''
        #for _x in self.intervals:
        raise NotImplementedError('don\'t ask why, I\'m just too lazy')
    
    def __repr__(self):
        s=''
        for x in self.intervals:
            s+=str(x)+'∪'
        return s[:-1]

class Sequence:
    '''get a mathmatic sequence
    with a function and a name'''
    def __init__(self,func,name,args=None,lenth=256):
        self.f=func
        self.l=[]
        self.args=args
        self.name=name
        self.len=lenth
    def get(self):
        for x in range(self.len):
            self.l.append(self.f(x,self.args))
    def serie(self,lenth=None,infin=True):
        if self.l==[]:
            self.get()
        if lenth==None:
            lenth=len(self.l)
        if infin and self.l[-1]>=self.l[0]:
            return inf
        return sum(self.l)
    def __getitem__(self,i):
        if self.l==[]:
            return self.f(i)
        else:
            return self.l[i]
    def __repr__(self):
        return '{'+self.name+'_n}'

def _Arith(n,a_0=0,d=None):
    if isinstance(a_0,tuple) :
        a_0,d=a_0
    return a_0+n*d
def _Geo(n,a_0=1,p=None):
    if isinstance(a_0,tuple) :
        a_0,p=a_0
    return a_0*(p**n)
Arithmetic=Sequence(_Arith,'a',(0,2))
Geometric=Sequence(_Geo,'a',(1,0.5))

class Po_func:  
    '''get a polynomial function
    instead of a python function;
    put a list of coefficient
    at coes'''
    def __init__(self, coes=[0],name='f',indep_var_name='x'):
        self.name=name
        self.indep_var_name=indep_var_name
        self.full_name=name+'('+indep_var_name+')'
        while coes[-1]==0 and len(coes)>1:
            coes.pop()
        self.coes=coes
        self.pow=len(coes)-1
    def __call__(self,x):
        y=0
        for n in range(len(self.coes)):
            y+=self.coes[n]*(x**n)
        return y
    def __add__(self,other):
        if isinstance(other,(int,float,Rational)):
            other = Po_func([other])
        p=len(self.coes)
        q=len(other.coes)
        new_coes=[]
        for x in range(max(p,q)):
            if x<min(p,q):
                new_coes.append(self.coes[x]+other.coes[x])
            else:
                new_coes.append(longer(self.coes,other.coes)[x])
        return Po_func(new_coes,'h')
    def __neg__(self):
        n_c=[]
        for _x in self.coes:
            n_c.append(-_x)
        return Po_func(n_c,'-f')
    def __sub__(self,other):
        return self+(-other)
    def __rsub__(self,other):
        return -self+other
    def __str__(self):
        s=n_to_s(self.coes[0])
        for n in range(1,self.pow+1):
            a=self.coes[n]
            if a!=0:
                s=n_to_s(a)+ self.indep_var_name+'^'+str(n)+s
        return s
    def __repr__(self):
        if DRAW_WHEN_REPR:draw_func(self)
        return self.full_name+'='+str(self)
    def __mul__(self,other):
        if isinstance(other,(Rational,int,float)) :
            new_coes=[]
            for x in range(self.pow+1):
                new_coes.append(self.coes[x]*other)
            return Po_func(new_coes)
        elif isinstance(other,Po_func):
            new_func=Po_func()
            for _x in range(other.pow+1):
                a=(self*other.coes[_x])._higher(_x)
                new_func+=a
            return new_func
        else :
            raise TypeError('Polynomial function can only be multiplied with nums or funcs')
    def __divmod__(self,other):
        if not isinstance(other,Po_func):
            raise TypeError('not available')
        f = self
        g = other
        new_coes=[]
        while f.pow>=g.pow:
            a=(f.coes[-1]/g.coes[-1])
            new_coes.insert(0,a)
            f-=g._higher(f.pow-g.pow)*a
            #print(f,g)
        return (Po_func(new_coes,'p'),f)
    def __pow__(self,other):
        if isinstance(other,int) and other>=0:
            new_func=Po_func([1])
            for _x in range(other):
                new_func*=self
            return new_func
        ##elif not ...:
        ##    pass
        else :
            raise TypeError('''at present, Po_funcs can only be raised to a integer greater than Zero
                if u have more questions please go to'''+AUTHERS_SPACE+'for further information')
    def _higher(self,a):
        '''the basic mathod of multiplying x**a'''
        return Po_func([0]*a+self.coes)
    def deriv(self):
        '''return the derivative of the function
        no agruments'''
        new_coes=[]
        for _x in range(1,self.pow+1):
            new_coes.append(_x*self.coes[_x])
        return Po_func(new_coes,self.name+"'")
    __rmul__=__mul__
    __radd__=__add__

x=Po_func([0,1],name='')

class Ra_func(Rational):
    '''rational functions instead of
    python functions,den and num must
    be both polynomial functions
    '''
    def __init__(self,num=Po_func([0]),den=Po_func([1])):
        if isinstance(num,Po_func) and isinstance(den,Po_func):
            self.num=num
            self.den=den
        else :
            raise TypeError('den and num must be both polynomial functions')
    def __call__(self,x):
        if self.den(x) != 0:
            return self.num(x)/self.den(x)
        elif self.num(x) != 0:
            return inf
        else :
            return nan


def hail_conjecture(x):
    if x>0 and int(x)==x:
        tm=0
        while x!=1:
            if x%2==0:
                x=x/2
            else:
                x=3*x+1
            喵=喵+1
        #print(喵)
        return 2**(喵-30)
    else:
        raise ArithmeticError('x can only be an integer bigger than zero')
### drawing functions ###
def coor_system(size=20,color=DEFAULT_COLOR):
    x_pen=turtle.Turtle()
    x_pen.color(color)
    x_pen.speed(0)
    y_pen=turtle.Turtle()
    y_pen.color(color)
    x_pen.speed(0)
    tp(x_pen,-400,0)
    tp(y_pen,0,-400)
    y_pen.lt(90)
    for num in range(-400,401,size):
        x_pen.write(num//size)
        x_pen.fd(size)
        y_pen.write(num//size)
        y_pen.fd(size)
    del x_pen,y_pen
def draw_func(f,delta=Rational(1,10),size=20,line=0,p=None,color=DEFAULT_COLOR,r=False):
    '''draw the graph of a function'''
    if p==None:
        if not isinstance(DEFAULT_PEN,turtle.Turtle):
            do_drawing()
        p=DEFAULT_PEN  
    p.color(color)
    if r:
        tp(p,0,f(Rational()))
        _x=Rational()
    else:
        tp(p,0,f(0))
        _x=0
        delta=float(delta)
    while float(_x)<=400/size:
        if line==0:p.goto(float(_x*size),float(f(_x))*size)
        else:
            tp(p,float(_x*size),float(f(_x))*size)
            p.dot(line)
        _x+=delta
    if r:
        tp(p,0,f(Rational()))
        _x=Rational()
    else:
        tp(p,0,f(0))
        _x=0
    while float(_x)>=-400/size:
        if line==0:p.goto(float(_x*size),float(f(_x))*size)
        else:
            tp(p,float(_x*size),float(f(_x))*size)
            p.dot(line)
        _x-=delta

### testing ###
if __name__=='__main__':
    def w0(x):
        if 0<x<=pi : return sqrt(x*(pi-x))
        elif pi<x<=tau:return -sqrt((x-pi)*(2*pi-x))
        else :return 0
    coor_system()
    _a=input('draw a function (0~3)')
    if _a=='0':
        draw_func(sin,color='#00ffcc')
        draw_func(cos,color='#ffb1c0')
    elif _a=='1':
        DEFAULT_PEN.ht()
        draw_func(hail_conjecture,1,0.1,1.5,color='#39c5bb')
    elif _a=='2':
        _b=input('compare?(T for true)')
        colors=['#ffb1c0','#ffff00','#00ffcc','#66ccff','#0080ff','#39c5bb','#ee0000']
        bn=[]
        for n in range(18):
            bn.append(fourier.series(n,False,w0))
        for n in range(1,8):
            if _b != 'T':DEFAULT_PEN.reset()
            def w(x):return fourier.wave(x,2*n,b=bn)
            draw_func(w,0.02,50,color=colors[n-1])
    elif _a=='3':
        bn=[]
        for q in range(200):
            bn.append(fourier.series(q,False,w0))
        def w(x):return fourier.wave(x,200,b=bn)
        draw_func(w,0.01,50)
    elif _a=='4':
        pass
 


回复

上一页1 页 / 共 1下一页
东雪莲东雪莲

emotion_编程猫_点赞

点赞0


评论


温柔的草灵灵532温柔的草灵灵532

有本事你加注释

点赞0


评论