使用python求和两个多项式的问题
问题描述:
我被要求编写一个程序来计算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?我真的不知道我应该在一开始写什么。我很抱歉,但我是编程新手,需要一个简单的代码,比如我的代码。
答
- 通过共同的约定,类名应该大写(即
Poly
) - 你有
__add__
做了很多的东西,没有任何与添加。这应该是一个警告标志。 - 很多
__add__
的工作都在关注数据存储格式。也许你应该使用更好的存储格式,不需要太多重新洗牌? -
__add__
中有很多重复的代码块;这通常是代码应该被分解到子程序中的一个指示器。 - 您有此对象(
self
)更改了另一个对象(L2
)的内部细节 - 另一种难闻的气味。
如果移动从__add__
自我(if len(self.coef) > len(self.deg) ...
)的标准化代码为__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"
需要注意的是:
- 每种方法很短,不相关的东西就应该完成的唯一的东西。
- 我故意写了
__init__
是非常容错的;它会高兴地接受给定功率的多个系数并对它们进行求和。这使我大大简化了__add__
和__mul__
,基本上只是将所有结果子句放在一个新的Poly中,并让它再次清理它们。 - 我已经包含了一个最小实现
__str__
,这将导致像5x^2 + -2x^1 + -5x^0
这样的中等难看的输出。您可能希望对负系数和1或0的幂加上特殊处理,以使其产生5x^2 - 2x - 5
。 - 这是为了理解,而不是抄袭;不要将它提交给你的老师,他将永远不会在一百万年内相信你真的写了它;-)
不是说它导致你的特定问题,但要小心使用'[]'作为默认值在'__init__'(或其他地方,就此而言):http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – lvc 2012-04-28 23:04:52
此外,它可能会更有意义将多项式存储为系数的单个列表,以便'x^3 + 2'具有系数'[1,0,2]'。 – lvc 2012-04-28 23:18:25
我都做过了!首先我的init没有[],但它不起作用。所以我会骑它。对不起,没有提到我期待用户输入一个字符串! – user1354396 2012-04-28 23:45:36