问题描述
这是我的代码:
def fact(y):
if y == 0:
fact=1
return fact
else:
fact=1
for k in range (1,y+1):
fact = fact * k
return fact
def e_negative_x(x):
n=0
numerical_precesion=1
numerical_precesion_ideal= 10**(-8)
while numerical_precesion > numerical_precesion_ideal:
sum=0
for i in range (0,n+1):
ind=((-x)**i)/fact(i)
if i> 0 & n-i == 0:
ind_2=((-x)**(i-1))/fact(i-1)
numerical_precesion_1 = ind_2 - ind
numerical_precesion = abs(numerical_precesion_1)
sum = sum + ind
if numerical_precesion > numerical_precesion_ideal:
n += 1
elif sum < 0:
n += 1
return sum
我尝试将其用于x=0.1;1;10;15
作为练习,但我的精度得到了“正确”,但是当我尝试x=30
时,它卡在了-8e-5
上(错误答案)。我试图增加我的条款,但是它仍然停留在-8e-5
上,小数点后一位不同,而且条款的大幅度增加之后根本没有改变。
编辑:这是-8e-5,这是错误的,因为在无穷大时该级数趋向于0。我进行了无限循环(对于无限项),并打印出它具有多少项以及该项的总和。我在关闭之前有600 +
个字词。在89
任期,我陷于-8e5
,在 117
之后,我陷于-8.553016433669241e-05
,直到600 +
任期。
解决方法
如何做得更好:
我想说,将可比较大小的正负项相加是容易出错的,因为这会导致将大数和小数相加,这被认为是有问题的。但自exp(-30)=1/exp(30).
1/math.fsum(((30)**n/math.factorial(n) for n in range(0,100+1)))
是
9.357622968840174e-14
即正像你期望的那样小。还有
1/math.fsum(((30)**n/math.factorial(n) for n in range(0,100+1)))-np.exp(-30)
给予
-1.262177448353619e-29
所以我们基本上和numpy一样。
错误在哪里:
这里是一张表格,其中以taylor级数总计N个项的方式近似计算exp(-30):
-
天真的想法,我只是将术语计算为浮点数并将其汇总。
-
在分数列中,我做了同样的事情,但使用的是python的分数,而不是浮点除法。
-
然后,我认为最好区分除/乘法和总结中的错误。因此,我用分数计算了每个被求和数,但在求和之前将它们转换为浮点数。
-
最后,我很自然地计算了exp(30)的值,然后又计算了我称为 1 / e ^ 30_trick 的1 / exp(30)的值。
native fractions float(fraction) 1/e^30_trick
0 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
10 1.212548e+08 1.212548e+08 1.212548e+08 4.187085e-09
20 8.529171e+10 8.529171e+10 8.529171e+10 2.652040e-12
30 3.848426e+11 3.848426e+11 3.848426e+11 1.706501e-13
40 6.333654e+10 6.333654e+10 6.333654e+10 9.670058e-14
50 8.782292e+08 8.782292e+08 8.782292e+08 9.360412e-14
60 1.685584e+06 1.685584e+06 1.685584e+06 9.357627e-14
70 6.225246e+02 6.225247e+02 6.225246e+02 9.357623e-14
80 5.588481e-02 5.595324e-02 5.588481e-02 9.357623e-14
90 -6.697346e-05 1.459487e-06 -6.697346e-05 9.357623e-14
100 -6.843293e-05 1.276217e-11 -6.843293e-05 9.357623e-14
110 -6.843294e-05 9.361706e-14 -6.843294e-05 9.357623e-14
120 -6.843294e-05 9.357623e-14 -6.843294e-05 9.357623e-14
我对结果很满意。由于它显示了朴素的方法,甚至是float(fractions)方法都非常糟糕,因此错误必须归纳为负和正项。同样,即使1 / exp(30)技巧和派系的确收敛到9.357623e-14的“正确”值。前者的收敛速度快于后者。
表格代码:
series = pd.Series(np.arange(0,151,10))
@np.vectorize
def naiv(N):
return math.fsum(((-30)**n/math.factorial(n) for n in range(0,N+1)))
@np.vectorize
def fractions(N):
return float(sum(Fraction((-30)**n,math.factorial(n)) for n in range(0,N+1)))
@np.vectorize
def float_fractions(N):
return math.fsum(float(Fraction((-30)**n,math.factorial(n))) for n in range(0,N+1))
@np.vectorize
def one_over_30_trick(N):
return 1/math.fsum(((30)**n/math.factorial(n) for n in range(0,N+1)))
pd.DataFrame({"native":naiv(series),"fractions":fractions(series),"float(fraction)":float_fractions(series),"1/e^30_trick":one_over_30_trick(series)},index=series)