我正在尝试使用Python v.2.7.5编写一个程序,它将计算x = 0和x = pi之间的曲线y = sin(x)下的区域。执行此计算,将x范围的n个分区改变为1到10(包括1和10),并打印近似值,真实值和百分比误差(换句话说,通过增加梯形数来提高精度)。将所有值打印到三位小数。
我不确定代码应该是什么样的。我被告知我应该只有大约12行代码才能完成这些计算。
我正在使用Wing IDE。
这是我到目前为止所拥有的
# base_n = (b-a)/n
# h1 = a + ((n-1)/n)(b-a)
# h2 = a + (n/n)(b-a)
# Trap Area = (1/2)*base*(h1+h2)
# a = 0, b = pi
from math import pi, sin
def TrapArea(n):
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)(((pi-0)/n)(sin((i-1)/n(pi-0))) + sin((i/n)(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
我不确定自己是否走在正确的轨道上。我收到一个错误,说“分配前引用的局部变量'sum'。有关如何改进我的代码的任何建议吗?
答案 0 :(得分:2)
Shashank Gupta回答的原始问题和问题是/n
整数除法。您需要先将n
转换为float
:
from math import pi, sin
def TrapArea(n):
sum = 0
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/float(n))*(sin((i-1)/float(n)*(pi-0))) + sin((i/float(n))*(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
输出:
0
0.785398163397
1.38175124526
1.47457409274
1.45836902046
1.42009115659
1.38070223089
1.34524797198
1.31450259385
1.28808354
请注意,您可以大大简化sum += ...
部分。
首先将所有(pi-0)
更改为pi
:
sum += (1.0/2.0)*((pi/float(n))*(sin((i-1)/float(n)*pi)) + sin((i/float(n))*pi))*deltax
然后尽可能pi/n
,这样就可以float
pi
已经float
,而无需拨打sum += (1.0/2.0)*(pi/n * (sin((i-1) * pi/n)) + sin(i * pi/n))*deltax
:
(1.0/2.0)
然后将0.5
更改为sum += 0.5 * (pi/n * sin((i-1) * pi/n) + sin(i * pi/n)) * deltax
并删除一些括号:
{{1}}
好多了,嗯?
答案 1 :(得分:1)
您的代码存在一些缩进问题,但这可能只是因为复制粘贴。无论如何,在sum = 0
函数的开头添加一行TrapArea
可以解决当前错误。但正如@Blender在评论中指出的那样,你有另一个问题,即浮点除法表达式*
之后缺少乘法运算符((1.0/2.0)
)。
请记住,在Python中,表达式并不总是按照您的数学方式进行评估。因此,(a op b)(c)
不会像您对数学表达式所期望的那样自动将a op b
的结果乘以c
。相反,这是Python中的函数调用符号。
另请记住,在使用其值进行赋值之前,必须初始化所有变量。 Python没有未命名变量的默认值,所以当你引用sum
sum += expr
的值相当于sum = sum + expr
时,你试图引用一个名称(sum
)根本没有绑定到任何对象。
您的功能的以下修订应该可以解决问题。注意我如何在你想要乘法的每个表达式之间放置乘法运算符(*
)。
def TrapArea(n):
sum = 0
for i in range(1, n):
i = float(i)
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/n)*(sin((i-1)/n*(pi-0))) + sin((i/n)*(pi-0)))*deltax
return sum
编辑:我还通过在循环的每次迭代中将i
转换为float(i)
来处理浮点除法问题。在Python 2.x中,如果将一个整数类型对象与另一个整数类型对象分开,则无论实际值如何,表达式都将计算为整数。
答案 2 :(得分:1)
一种“更好”的方法来制作具有等间距点的梯形规则......
设dx = pi/n
为区间的宽度。另外,让f(i)为sin(i * dx)以缩短下面的一些表达式。然后间隔i(在range(1,n)
中)贡献:
dA = 0.5*dx*( f(i) + f(i-1) )
...总和(这是一个区域,所以我使用dA代表“delta area”)。考虑到0.5 * dx,使整体看起来像:
A = 0.5*dx * ( (f(0) + f(1)) + (f(1) + f(2)) + .... + (f(n-1) + f(n)) )
请注意,在最多两个f(n-1)项上有两个f(1)项,两个f(2)项。将这些结合起来:
A = 0.5*dx * ( f(0) + 2*f(1) + 2*f(2) + ... + 2*f(n-1) + f(n) )
除第一项和最后一项外,0.5和2因素取消:
A = 0.5*dx(f(0) + f(n)) + dx*(f(1) + f(2) + ... + f(n-1))
最后,你可以将dx完全排除在最后只做一次乘法。转换回sin()调用,然后:
def TrapArea(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi)) # this is 0 for this problem, but not others
for i in range(1, n-1):
asum += sin(i*dx)
return sum*dx
将“sum”改为“asum”,或者“area”可能会更好。这主要是因为sum()是一个内置函数,我将在线下使用。
额外功劳:总和的循环部分可以通过生成器表达式和sumin内置函数一步完成:
def TrapArea2(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi))
asum += sum(sin(i*dx) for i in range(1,n-1))
return asum*dx
测试这两个:
>>> for n in [1, 10, 100, 1000, 10000]:
print n, TrapArea(n), TrapArea2(n)
1 1.92367069372e-16 1.92367069372e-16
10 1.88644298557 1.88644298557
100 1.99884870579 1.99884870579
1000 1.99998848548 1.99998848548
10000 1.99999988485 1.99999988485
第一行是“数字零”,因为math.sin(math.pi)的计算结果大约为1.2e-16而不是零。绘制从0到pi的单个区间,端点确实都是0(或几乎是这样。)