Python计算错误
我正在使用 API mpmath 来计算以下总和
让我们考虑由以下定义的系列 u0、u1、u2:
u0 = 3/2 = 1,5
u1 = 5/3 = 1,6666666…
un+1 = 2003 - 6002/un + 4000/un un-1
系列收敛于 2,但由于舍入问题,它似乎收敛于 2000。
n Calculated value Rounded off exact value 2 1,800001 1,800000000 3 1,890000 1,888888889 4 3,116924 1,941176471 5 756,3870306 1,969696970 6 1996,761549 1,984615385 7 1999,996781 1,992248062 8 1999,999997 1,996108949 9 2000,000000 1,998050682 10 2000,000000 1,999024390
我的代码:
from mpmath import *
mp.dps = 50
u0=mpf(3/2.0)
u1=mpf(5/3.0)
u=[]
u.append(u0)
u.append(u1)
for i in range (2,11):
un1=(2003-6002/u[i-1]+(mpf(4000)/mpf((u[i-1]*u[i-2]))))
u.append(un1)
print u
我的坏结果:
[mpf('1.5'),
mpf('1.6666666666666667406815349750104360282421112060546875'),
mpf('1.8000000000000888711326751945268011597589466120961647'),
mpf('1.8888888889876302386905492787148253684796100079942617'),
mpf('1.9411765751351638992775070422559330255517747908588059'),
mpf('1.9698046831709839591526211645628191427874374792786951'),
mpf('2.093979191783975876606205176530675127058752077926479'),
mpf('106.44733511712489354422046139349654833300787666477228'),
mpf('1964.5606972399290690749220686397494349501387742896911'),
mpf('1999.9639916238009625032390578545797067344576357100626'),
mpf('1999.9999640260895343960004614025893194430187653900418')]
我尝试与其他一些函数(fdiv ...)一起执行或更改精度:同样糟糕的结果
这段代码有什么问题?
问题: 如何更改我的代码以找到值 2.0 ???公式为:
un+1 = 2003 - 6002/un + 4000/un un-1
谢谢
I’m using the API mpmath to compute the following sum
Let us consider the serie u0, u1, u2 defined by:
u0 = 3/2 = 1,5
u1 = 5/3 = 1,6666666…
un+1 = 2003 - 6002/un + 4000/un un-1
The serie converges on 2, but with rounding problem it seems to converge on 2000.
n Calculated value Rounded off exact value 2 1,800001 1,800000000 3 1,890000 1,888888889 4 3,116924 1,941176471 5 756,3870306 1,969696970 6 1996,761549 1,984615385 7 1999,996781 1,992248062 8 1999,999997 1,996108949 9 2000,000000 1,998050682 10 2000,000000 1,999024390
My code :
from mpmath import *
mp.dps = 50
u0=mpf(3/2.0)
u1=mpf(5/3.0)
u=[]
u.append(u0)
u.append(u1)
for i in range (2,11):
un1=(2003-6002/u[i-1]+(mpf(4000)/mpf((u[i-1]*u[i-2]))))
u.append(un1)
print u
my bad results :
[mpf('1.5'),
mpf('1.6666666666666667406815349750104360282421112060546875'),
mpf('1.8000000000000888711326751945268011597589466120961647'),
mpf('1.8888888889876302386905492787148253684796100079942617'),
mpf('1.9411765751351638992775070422559330255517747908588059'),
mpf('1.9698046831709839591526211645628191427874374792786951'),
mpf('2.093979191783975876606205176530675127058752077926479'),
mpf('106.44733511712489354422046139349654833300787666477228'),
mpf('1964.5606972399290690749220686397494349501387742896911'),
mpf('1999.9639916238009625032390578545797067344576357100626'),
mpf('1999.9999640260895343960004614025893194430187653900418')]
I tried to perform with some others functions (fdiv…) or to change the precision: same bad result
What’s wrong with this code ?
Question:
How to change my code to find the value 2.0 ??? with the formula :
un+1 = 2003 - 6002/un + 4000/un un-1
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用十进制模块,您可以看到级数在 2000 处也有一个收敛解:
递推关系有多个不动点(一个在 2 处,另一个在 2000 处):
2 处的解是不稳定的不动点。 有吸引力的定点位于 2000。
收敛非常接近到 2,当四舍五入导致该值稍微超过 2 时,该差异会一次又一次地放大,直到达到 2000。
Using the decimal module, you can see the series also has a solution converging at 2000:
The recurrence relation has multiple fixed points (one at 2 and the other at 2000):
The solution at 2 is an unstable fixed-point. The attractive fixed-point is at 2000.
The convergence gets very close to two and when the round-off causes the value to slightly exceed two, that difference gets amplified again and again until hitting 2000.
您的(非线性)递归序列具有三个固定点:
1
、2
和2000
。与 2000 相比,值 1 和 2 彼此接近,这通常表明不动点不稳定,因为它们“几乎”是双根。你需要做一些数学计算,才能避免过早出现分歧。令
v(n)
为边序列:以下情况成立:
然后您可以简单地计算
v(n)
并推导u(n)
来自u(n) = v(n)/(1+2^n)
:结果:
请注意,这最终仍然会发散。为了真正收敛,您需要以任意精度计算 v(n)。但现在这要容易得多,因为所有值都是整数。
Your (non-linear) recurrence sequence has three fixed points:
1
,2
and2000
. The values 1 and 2 are close to each other compared to 2000, which is usually an indication of unstable fixed points because they are "almost" double roots.You need to do some maths in order to diverge less early. Let
v(n)
be a side sequence:The following holds true:
You can then simply compute
v(n)
and deduceu(n)
fromu(n) = v(n)/(1+2^n)
:And the result:
Note that this will still diverge eventually. In order to really converge, you need to compute
v(n)
with arbitrary precision. But this is now a lot easier since all the values are integers.您以 53 位精度计算初始值,然后将该舍入值分配给高精度 mpf 变量。您应该使用 u0=mpf(3)/mpf(2) 和 u1=mpf(5)/mpf(3)。再进行几次迭代后,您将保持接近 2,但最终仍会收敛于 2000。这是由于舍入误差造成的。一种替代方法是使用分数进行计算。我使用了 gmpy 并且以下代码收敛到 2。
You calculate your initial values to 53-bits of precision and then assign that rounded value to the high-precision mpf variable. You should use u0=mpf(3)/mpf(2) and u1=mpf(5)/mpf(3). You'll stay close to 2 for a few more interations, but you'll still end up converging at 2000. This is due to rounding error. One alternative is to compute with fractions. I used gmpy and the following code converges to 2.
如果您以无限精度计算,那么您将得到
2
否则您将得到2000
:输出
If you compute with infinite precision then you get
2
otherwise you get2000
:Output
好吧,正如 casevh 所说,我只是在代码中以首字母缩写形式添加了 mpf 函数:
u0=mpf(3)/mpf(2)
u1=mpf(5)/mpf(3)
并且值收敛 16 个步骤再次偏离之前的正确值 2.0(见下文)。
因此,即使有一个很好的用于任意精度浮点运算和一些基本运算的Python库,结果也可能变得完全错误,并且它不是我有时读到的算法、数学或递归问题。
所以有必要保持警惕和批评! (我非常担心 mpmath.lerchphi(z, s, a) 函数;-)
Well, as casevh said, I just added the mpf function in first initials terms in my code :
u0=mpf(3)/mpf(2)
u1=mpf(5)/mpf(3)
and the value converge for 16 steps to the correct value 2.0 before diverged again (see below).
So, even with a good python library for arbitrary-precision floating-point arithmetic and some basics operations the result can become totally false and it is not algorithmic, mathematical or recurrence problem as I read sometimes.
So it is necessary to remain watchful and critic !!! ( I’m very afraid about the mpmath.lerchphi(z, s, a) function ;-)
递归关系的精确解(初始值 u_0 = 3/2,u_1 = 5/3)很容易被验证为
您看到的问题是,尽管解是这样的,但
这个限制是令人排斥的 递归关系的固定点。也就是说,对于某些 n,任何偏离 u_{n-1}、u{n-2} 正确值的情况都将导致值进一步偏离正确限制。因此,除非您的递归关系实现正确地表示每个 u_n 值准确,否则预计它最终会偏离正确的限制,收敛到恰好是唯一的错误值 2000吸引你的递归关系的固定点。
(*) In fact, u_n = (2^(n+1) + 1) / (2^n + 1) is the solution to any recurrence relation of the form
具有与上面给出的相同的初始值,其中C是任意常数。如果我在查找特征多项式的根时没有犯错误,则这将具有一组固定点 {1, 2, C - 3}\{0}。极限 2 可以是排斥固定点或吸引固定点,具体取决于 CEg 的值,对于 C = 2003,固定点集是 {1, 2, 2000},其中 2 是排斥点,而对于 C = 3 不动点是 {1, 2},其中 2 是吸引子。
The exact solution to your recurrence relation (with initial values u_0 = 3/2, u_1 = 5/3) is easily verified to be
The problem you're seeing is that although the solution is such that
this limit is a repelling fixed point of your recurrence relation. That is, any departure from the correct values of u_{n-1}, u{n-2}, for some n, will result in further values diverging from the correct limit. Consequently, unless your implementation of the recurrence relation correctly represents every u_n value exactly, it can be expected to exhibit eventual divergence from the correct limit, converging to the incorrect value of 2000 that just happens to be the only attracting fixed point of your recurrence relation.
(*) In fact, u_n = (2^(n+1) + 1) / (2^n + 1) is the solution to any recurrence relation of the form
with the same initial values as given above, where C is an arbitrary constant. If I haven't made a mistake finding the roots of the characteristic polynomial, this will have the set of fixed points {1, 2, C - 3}\{0}. The limit 2 can be either a repelling fixed point or an attracting fixed point, depending on the value of C. E.g., for C = 2003 the set of fixed points is {1, 2, 2000} with 2 being a repellor, whereas for C = 3 the fixed points are {1, 2} with 2 being an attractor.