1

이 클래스는 유한 필드 다항 문자열을 가져 와서 구문 분석하고 (+ - */%) 연산 한 다음 입력과 같은 형식으로 출력합니다. 그것은 잘 작동합니다 (지금까지). 그러나 이제는 산술 연산자에 대한 특수 메서드를 구현하려고하는데 단순히 문자열을 연결하는 지점을 지나칠 수 없습니다. 일반적으로, 그 아이디어는 클래스 인스턴스로 입력을 초기화하는 것이지만,이 경우에는 입력을 정규식으로 처리하는 시도가 복잡해 보입니다. 저는 제 스스로에게 파이썬을 가르치고 있습니다. 그래서 이것은 나를위한 공포 영화이지만, 노련한 파이썬 프로그래머를위한 장난감 일 것입니다. 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 

여기에 클래스의와 예 내가 사용 :

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 

출력 :

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) 

하단 마지막 예는 문제점을 나타내는

>>> 
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에서 볼 수 있듯이이 두 가지를 +를 사용하여 연결해야합니다. 또한이 상황에서 S-expression 트리를 사용해야하는지 알고 싶습니다.

편집 :

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__' 메쏘드가 호출됩니다. 이를 제거하면 클래스의 인쇄 객체가 덜 유용한 결과를 얻게됩니다.내가 리팩토링 할 때 코드를 완전히 이해하지 못했기 때문에 prepBinary()에서 parsePolyToListInput()을 사용하는 것이 다소 임의적이었습니다. 지금은 더 잘 이해하고 몇 분 정도 무료로 사용할 수 있으므로 다시 수정하고 내 게시물을 편집 할 것입니다. – jcrudy

관련 문제