1

該類使用有限字段多項式字符串,解析它,操作(+ - * /%),然後以與輸入相同的格式輸出。它工作正常(到目前爲止)。但是,現在我正試圖在算術運算符上實現特殊的方法,並且我無法超越簡單連接字符串的地步。一般來說,這個想法是將輸入初始化爲一個類實例,但在這種情況下,輸入有一個正則表達式,似乎使任何嘗試都這樣做變得複雜。我在教自己的Python,所以這對我來說是一部恐怖電影,但可能只是任何經驗豐富的Python程序員的玩具。Python - 使用現有類方法的特殊方法算術

這些似乎有大量的信息,但我不知道他們在這種情況下,有多少是有幫助的:

http://stackoverflow.com/questions/10842166/programmatically-create-arithmetic-special-methods-in-python-aka-factory-funct 
http://rosettacode.org/wiki/S-Expressions 
http://www.greenteapress.com/thinkpython/thinkCSpy/html/chap14.html 
http://docs.cython.org/src/userguide/special_methods.html 

這裏的類和例子我使用:

import re 

class gf2pim: 

def id(self,lst): 
    """returns modulus 2 (1,0,0,1,1,....) for input lists""" 
    return [int(lst[i])%2 for i in range(len(lst))] 

def listToInt(self,lst): 
    """converts list to integer for later use""" 
    result = self.id(lst) 
    return int(''.join(map(str,result))) 

def parsePolyToListInput(self,poly): 
    """performs regex on raw string and converts to list""" 
    c = [int(i.group(0)) for i in re.finditer(r'\d+', poly)] 
    return [1 if x in c else 0 for x in xrange(max(c), -1, -1)] 

def prepBinary(self,x,y): 
    """converts to base 2; bina,binb are binary values like 110100101100.....""" 
    x = self.parsePolyToListInput(x); y = self.parsePolyToListInput(y) 
    a = self.listToInt(x); b = self.listToInt(y) 
    bina = int(str(a),2); binb = int(str(b),2) 
    return bina,binb # 

def add(self,a,b): 
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns binary string""" 
    bina,binb = self.prepBinary(a,b) 
    return self.outFormat(bina^binb) 

def subtract(self,x,y): 
    """same as addition in GF(2)""" 
    return self.add(x,y) 

def quotient(self,a,b): 
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns quotient formatted as polynomial""" 
    a,b = self.prepBinary(a,b) 
    return self.outFormat(a/b) 

def remainder(self,a,b): 
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns remainder formatted as polynomial""" 
    a,b = self.prepBinary(a,b) 
    return self.outFormat(a%b) 

def outFormat(self,raw): 
    """process resulting values into polynomial format""" 
    raw = "{0:b}".format(raw); raw = str(raw[::-1]); g = [] #reverse binary string for enumeration 
    g = [i for i,c in enumerate(raw) if c == '1'] 
    processed = "x**"+" + x**".join(map(str, g[::-1])) 
    if len(g) == 0: return 0 #return 0 if list empty 
    return processed #returns result in gf(2) polynomial form 

def __add__(self,other): 
    return gf2pim.add(self,other) 

底部的最後一個例子說明這個問題:

obj = gf2pim() 
a = "x**14 + x**1 + x**0"; b = "x**6 + x**2 + x**1" 
c = "x**2 + x**1 + x**0"; d = "x**3 + x**1 + x**0" 
e = "x**3 + x**2 + x**1 + x**0"; f = "x**2"; g = "x**1 + x**0"; h = "x**3 + x**2 + x**0" 
p = "x**13 + x**1 + x**0"; q = "x**12 + x**1"; j = "x**4 + x**3 + x**1 + x**0" 
print "add: [%s] + [%s] = %s "%(a,b,obj.add(a,b)) 
print "add: [%s] + [%s] = %s "%(c,d,obj.add(c,d)) 
print "quotient (max(a,b)/min(a,b): [%s]/[%s] = %s "%(a,b,obj.quotient(a,b)) 
print "remainder (max(a,b) mod min(a,b)): [%s] mod [%s] = %s "%(a,b,obj.remainder(a,b)) 
print "quotient (max(a,b)/min(a,b): [%s]/[%s] = %s "%(c,d,obj.quotient(c,d)) 
print "remainder (max(a,b) mod min(a,b): [%s] mod [%s] = %s "%(c,d,obj.remainder(c,d)) 
print "quotient (max(a,b)/min(a,b): [%s]/[%s] = %s "%(q,q,obj.quotient(q,q)) 
print "remainder (max(a,b) mod min(a,b): [%s] mod [%s] = %s "%(q,q,obj.remainder(q,q)) 
print "modular_inverse: [%s] * [%s] mod [%s] = 1 [%s]"%(p,valuemi2[0],q,valuemi2[1]) 
sum1 = obj.add(a,b); quotient1 = obj.quotient(sum1,c) 

### HERE THE PROBLEM IS CLEAR 
print "[(a+b)/c] = ",quotient1 
smadd1 = a+b 
print "smadd1 ",smadd1 

和輸出:

>>> 
add: [x**14 + x**1 + x**0] + [x**6 + x**2 + x**1] = x**14 + x**6 + x**2 + x**0 
add: [x**2 + x**1 + x**0] + [x**3 + x**1 + x**0] = x**3 + x**2 
quotient (max(a,b)/min(a,b): [x**14 + x**1 + x**0]/[x**6 + x**2 + x**1] = x**7 + x**6 + x**5 + x**3 + x**1 
remainder (max(a,b) mod min(a,b)): [x**14 + x**1 + x**0] mod [x**6 + x**2 + x**1] = x**2 + x**1 + x**0 
quotient (max(a,b)/min(a,b): [x**2 + x**1 + x**0]/[x**3 + x**1 + x**0] = 0 
remainder (max(a,b) mod min(a,b): [x**2 + x**1 + x**0] mod [x**3 + x**1 + x**0] = x**2 + x**1 + x**0 
quotient (max(a,b)/min(a,b): [x**12 + x**1]/[x**12 + x**1] = x**0 
remainder (max(a,b) mod min(a,b): [x**12 + x**1] mod [x**12 + x**1] = 0 
[(a+b)/c]*d = x**14 + x**12 + x**9 + x**1 
smadd1 x**14 + x**1 + x**0x**6 + x**2 + x**1 
>>> 

因此,你可以看到smadd1我需要使用+而不是僅僅連接來添加這2個。另外,我想知道在這種情況下是否需要使用S表達式樹。

編輯:

乘(),這是工作,但不是現在:

def __mul__(self,other): 
    """ 
    __multiply__ is the special method for overriding the - operator 
    returns product of 2 polynomials in gf2; self,other are values 10110011... 
    """ 
    self = int(str(self),2) 
    bitsa = reversed("{0:b}".format(self)) 
    g = [(other<<i)*int(bit) for i,bit in enumerate(bitsa)] 
    return gf2infix(self.outFormat(reduce(lambda x,y: x^y,g))) 

它最初的形式是:

def multiply(self,a,b): 
    """a,b are GF(2) polynomials like x**7 + x**3 + x**0... ; returns product of 2 polynomials in gf2""" 
    a = self.prepBinary(a); b = self.prepBinary(b) 
    bitsa = reversed("{0:b}".format(a)) 
    g = [(b<<i)*int(bit) for i,bit in enumerate(bitsa)] 
    return self.outFormat(reduce(lambda x,y: x^y,g)) 

無視問題與multiply(),我修好了它。被更改的行是:

bitsa = reversed("{0:b}".format(self.bin)) 

和之前的行被取出。

回答

1

看起來你混淆了兩個概念:表示有限域多項式的字符串和類gf2pim的對象,它也表示有限域多項式。您應該爲您希望操作的每個多項式實例化一個gf2pim對象,並且對gf2pim對象的操作應返回其他gf2pim對象。目前您正嘗試在2個字符串上使用+運算符,這就是您的__add__方法未被調用的原因。您定義的gf2pim類還有其他一些問題。我已經將代碼重構了一下,儘管它還不完美。我也忽略了劃分方法,但我認爲我所做的應該讓你走上正確的軌道。有關運算符重載的更多特殊方法名稱,請參閱此link的第3.4.8節。

import re 
class gf2pim(object):#Your classes should generally inherit from object 


    def __init__(self, binary): 
     '''__init__ is a standard special method used to initialize objects. Here __init__ 
     will initialize a gf2pim object based on a binary representation.''' 
     self.bin = binary 

    @classmethod 
    def from_string(cls, string): 
     return cls(cls._string_to_binary(string)) 

    def to_string(self): 
     raw = "{0:b}".format(self.bin); raw = str(raw[::-1]); g = [] #reverse binary string for enumeration 
     g = [i for i,c in enumerate(raw) if c == '1'] 
     processed = "x**"+" + x**".join(map(str, g[::-1])) 
     if len(g) == 0: return 0 #return 0 if list empty 
     return processed #returns result in gf(2) polynomial form 

    @classmethod 
    def id(cls, lst): 
     """returns modulus 2 (1,0,0,1,1,....) for input lists""" 
     return [int(lst[i])%2 for i in range(len(lst))] 

    @classmethod 
    def _list_to_int(self, lst): 
     """converts list to integer for later use""" 
     result = self.id(lst) 
     return int(''.join(map(str,result))) 

    @classmethod 
    def _string_to_list(cls, string): 
     """performs regex on raw string and converts to list""" 
     c = [int(i.group(0)) for i in re.finditer(r'\d+', string)] 
     return [1 if x in c else 0 for x in xrange(max(c), -1, -1)] 

    @classmethod 
    def _string_to_binary(cls, string): 
     """converts to base 2; bina,binb are binary values like 110100101100.....""" 
     x = cls._string_to_list(string) 
     a = cls._list_to_int(x) 
     bina = int(str(a),2) 
     return bina # 

    def __add__(self,other): 
     """ 
     __add__ is another special method, and is used to override the + operator. This will only 
     work for instances of gf2pim and its subclasses. 

     a,b are GF(2) polynomials like x**7 + x**3 + x**0 ...; returns binary string""" 
     return gf2pim(self.bin^other.bin) 

    def __sub__(self,other): 
     """ 
     __sub__ is the special method for overriding the - operator 

     same as addition in GF(2)""" 
     return self.add(other) 

    def __str__(self): 
     return self.to_string() 

if __name__ == '__main__': 
    a = gf2pim.from_string("x**14 + x**1 + x**0") 
    b = gf2pim.from_string("x**6 + x**2 + x**1") 
    smadd1 = a+b 
    print "smadd1 ",smadd1   
+0

是的謝謝你,正是我需要的。我不知道你爲什麼使用__str __(self)方法。是隻爲__init __()和爲什麼?你爲什麼要移動prepBinary()之外的parsePolyToListInput()以在__init __()方法中自己初始化? – stackuser

+0

使用'print'時會調用'__str__'方法。嘗試刪除它,你會看到從你的類打印對象提供了一個不太有用的結果。我沒有完全理解你的代碼,因爲我正在重構,所以我選擇將parsePolyToListInput()移出prepBinary()有點武斷。我現在更瞭解它,並有幾分鐘免費,所以我會重構它並編輯我的文章。 – jcrudy