2012-04-28 5 views
1

Я прошу сделать программу, которая вычисляет добавление двух полиномов от n и m степеней. Я сделал два словаря (один для первого многочлена, а другой для другого полинома), поскольку каждый из них имеет коэффициенты как значения и степени как ключи, так что я могу проверить, идентичны ли ключи из обоих словарей, тогда я могу суммировать их значения. Но я не знаю, почему я всегда получаю сообщение об ошибке. Мой код до сих пор:Проблемы с суммированием двух полиномов с использованием python

class poly: 
    def __init__(self, L=[], D=[]): 
     self.coef=L 
     self.deg=D 

    def __add__(self,L2): 
     if len(self.coef)>len(self.deg): 
      dec=dict(zip(self.deg,self.coef)) 
      dec[0]=self.coef[-1] 

     else: 
      dec=dict(zip(self.deg,self.coef)) 

     Dec1=dec 

     if len(L2.coef)>len(L2.deg): 
      dec=dict(zip(L2.deg,L2.coef)) 
      dec[0]=L2.coef[-1] 
     else: 
      dec=dict(zip(L2.deg,L2.coef)) 

     Dec2=dec 
     p=[] 

     if len(Dec2)>len(Dec1): 
      for i in Dec2: 
      if i in Dec1: 
       s=Dec1[i]+Dec2[i] 
       p=p+[s] 
      else: 
       p=p+p[Dec2[i]] 

      for x in Dec1: 
      if x in Dec2: 
       p=p 
      else: 
       p=p+[dec1[x]] 
     return(poly(p)) 

     if len(Dec2)<len(Dec1): 
     for x in Dec1: 
      if x in Dec2: 
       g=Dec1[x] 
       p=p+[g] 
      else: 
       p=p+[Dec1[x]] 

     for m in Dec2: 
      if m in Dec1: 
       p=p 
      else: 
       p=p+[Dec2[m]] 
     return (poly(p)) 

Этот код не работает для всех моих примеров, таких как

>>> p=poly([2,4,7,34],[6,4,2]) 
>>> p1=poly([6,3,7,2,8],[8,4,2,1]) 
>>> p2=p+p1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    p2=p+p1 
    File "poly.py", line 31, in __add__ 
    p=p+p[Dec2[i]] 
IndexError: list index out of range 
>>> #The numbers in the first list is the coefficients and the second list is for degrees 

Это не работает! Но это сработало, когда я сделал дополнение без использования метода класса. Я новичок, и я сделал все возможное, чтобы исправить эту проблему.

Другой вопрос: как написать def str для моего кода? Я действительно не знаю, что я должен писать в начале. Мне жаль, ребята, но я новичок в программировании, и мне нужен простой код, такой как мой.

+0

Не то, чтобы это вызывало вашу конкретную проблему, но будьте осторожны с использованием '[]' в качестве значения по умолчанию в '__init__' (или где-нибудь еще, если на то пошло): http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – lvc

+2

Кроме того, это может иметь смысл сохраните свой многочлен как единый список коэффициентов, так что 'x^3 + 2' имеет коэффициенты' [1, 0, 2] '. – lvc

+0

Я сделал оба! сначала мой init был без [], но это не сработало. Так что я поеду. Извините, что не упомянул, что я ожидаю, что пользователь войдет в строку !! – user1354396

ответ

2
  1. По общему соглашению, имена классов должны быть капитализированы (т.е. Poly)
  2. Вы __add__ делать много вещей, которые не имеют ничего общего с добавлением. Это должно быть предупреждающим знаком.
  3. Много работы __add__ работает с форматом хранения данных. Может быть, вы должны использовать более удобный формат хранения, который не будет нуждаться в перестановке?
  4. У вас много повторяющихся фрагментов кода в __add__; это обычно показатель того, что код должен быть учтен в подпрограмме.
  5. У вас есть этот объект (self), вносящий изменения во внутренние детали другого объекта (L2) - еще один неприятный запах.

Если вы перемещаете код нормализации для себя (if len(self.coef) > len(self.deg) ...) из __add__ в __init__, это будет решать # 2, # 3, половина # 4 и # 5 все на одном дыхании (вам больше не придется " сделайте «L2», он «сделает» сам).

Если вы понимаете, что это практически не имеет значения, будь то len(Dec1) > len(Dec2) или нет, вы можете избавиться от другого блока избыточного кода. Это фиксирует вторую половину # 4. Внезапно __add__ сжимается от 48 строк кода до 12, и становится намного легче понять и отладить.

Для сравнения:

from itertools import izip_longest, chain, product 
from collections import defaultdict 

class Poly(object): 
    def __init__(self, coeff=None, power=None): 
     if coeff is None: coeff = [] 
     if power is None: power = [] 
     self.d = defaultdict(int) 
     for c,p in izip_longest(coeff, power, fillvalue=0): 
      if c != 0: 
       self.d[p] += c 

    @classmethod 
    def fromDict(cls, d): 
     return cls(d.itervalues(), d.iterkeys()) 

    @property 
    def degree(self): 
     return max(p for p,c in self.d.iteritems() if c != 0) 

    def __add__(self, poly): 
     return Poly(
      chain(self.d.itervalues(), poly.d.itervalues()), 
      chain(self.d.iterkeys(), poly.d.iterkeys()) 
     ) 

    def __mul__(self, poly): 
     return Poly(
      (cs*cp for cs,cp in product(self.d.itervalues(), poly.d.itervalues())), 
      (ps+pp for ps,pp in product(self.d.iterkeys(), poly.d.iterkeys())) 
     ) 

    def __call__(self, x): 
     return sum(c*x**p for p,c in self.d.iteritems()) 

    def __str__(self): 
     clauses = sorted(((p,c) for p,c in self.d.iteritems() if c != 0), reverse=True) 
     return " + ".join("{}x^{}".format(c,p) for p,c in clauses) or "0" 

Обратите внимание, что:

  1. Каждый метод коротка и делает только то, что отношение к предполагается достичь.
  2. Я целенаправленно написал __init__, чтобы быть очень отказоустойчивым; он будет с радостью принимать множественные коэффициенты заданной мощности и суммировать их. Это позволило мне значительно упростить __add__ и __mul__, в основном просто бросая все полученные предложения в новый Poly и позволяя им очищать их снова.
  3. Я включил минимальную реализацию __str__, что приведет к умеренно уродливому выходу, например 5x^2 + -2x^1 + -5x^0.Возможно, вы захотите добавить специальную обработку для отрицательных коэффициентов и степеней 1 или 0, чтобы вместо этого произвести 5x^2 - 2x - 5.
  4. Это для понимания, а не для плагиата; не отправляйте его своему учителю, как есть, он никогда не сможет через миллион лет полагать, что вы его на самом деле написали ;-)
Смежные вопросы