【问题标题】:Euler's Approximation欧拉近似
【发布时间】:2020-07-29 01:35:19
【问题描述】:

我正在尝试为微分方程的欧拉近似制作一个程序(我在一本书中遇到了一个问题告诉我)。我设法编写了适用于所有事物的东西(至少我已经测试过)但是由于某种原因,它在 step = 0,1 失败...... 代码如下:

from math import pow as p

y0: int = 3

h = input("Step size:")
h =float(h)
h1 = h
x_n=0
while x_n < (1):
    yn = y0 + h*(3*(p(x_n ,2))*(2-y0))
    x_n=h1
    h1=h1+h
    y0=yn
else:
    print(yn)

# h(1),f(1)=3
# h(0.1),f(1)=2,39279
# h(0.01),f(1)=2.37011
# h(0.001),f(1)=2.36810

它适用于 h=1、h=0.5、h=0.2、h=0.05、h=0.01、h=0.001 等等......由于某种原因,它只在 h=0.1 时失败。

有问题的微分方程是 y'=3(x^2)(2-y)

感谢您的帮助!

【问题讨论】:

  • 当你说“失败”时,你的意思是它在最终的yn中得到了错误的答案?
  • 您的代码是正确的,h = 0.1 的结果是 2.274955739773159。您是否将其与一本书的结果进行比较?也许你实现了一些错误的代码,检查方程和初始参数。
  • 如果您知道该网站,我使用了欧拉近似值和 slader.com 的在线计算器,他们都说对于 h=0.1,结果应该是 2.36 或类似的东西......
  • emathhelp.net/calculators/differential-equations/… 这是我用来检查我的代码的网站。
  • 这也是我用来验证的 slader 帖子,它是由某个人用另一个欧拉计算器完成的。slader.com/textbook/…

标签: python math differential-equations calculus


【解决方案1】:

您的代码没有问题。 (您也可以使用** 代替pow;例如pow(2,3) = 2**3 = 8

【讨论】:

  • 感谢您的帮助,该图应该代表什么?另外我知道 ** 我只是更喜欢 pow :D。问题是当我在网上查找欧拉近似值计算器时,它给了我 2.36或与 slader.com 类似和相同的东西(这是一个检查问题答案的网站)
  • 对不起,应该标记轴。 . x 轴是h,y 轴是yn。解析解是 y=exp(-x^3) + 2,这意味着 yn = y(1) = 2 + 1/e。并且您的解决方案是正确的,前提是步长足够小。
【解决方案2】:

(如果变量名有一个统一的结构会更好看)

如果你也打印出最后一步的时间

for h in [1.0,0.5,0.2,0.1,0.05]:
    x_n, y_0 = 0.0, 3.0
    while x_n < (1):
        y_n = y_0 + h*(3*(x_n**2)*(2-y_0))
        x_n = x_n + h
        y_0 = y_n
    else:
        print(f"h={h}: f({x_n:12.10f}) = {y_n:12.10f}")

然后你在结果中找到

h= 1.00000: f(1.0000000000) = 3.0000000000
h= 0.50000: f(1.0000000000) = 2.6250000000
h= 0.20000: f(1.0000000000) = 2.4261034230
h= 0.10000: f(1.1000000000) = 2.2749557398
h= 0.05000: f(1.0000000000) = 2.3795619396

确实在h=0.1 迭代只在x=1.1 停止。这是由于变量的浮点格式,靠近x=1 的点x_n 可能很快落在下面,因此执行另一个步骤。防止这种情况的一种方法是调整最后一步(另一种是使用“近距离”比较)

for h in [1.0,0.5,0.2,0.1,0.05]:
    x_n, y_0, x_f = 0.0, 3.0, 1.0
    y_n = y_0
    while x_n < x_f:
        if x_n + 1.001*h > x_f: h = x_f - x_n
        y_n = y_n + h*(3*(x_n**2)*(2-y_n))
        x_n = x_n + h
    else:
        print(f"h={h:8.5f}: f({x_n:12.10f}) = {y_n:12.10f}")

结果更一致

h= 1.00000: f(1.0000000000) = 3.0000000000
h= 0.50000: f(1.0000000000) = 2.6250000000
h= 0.20000: f(1.0000000000) = 2.4261034230
h= 0.10000: f(1.0000000000) = 2.3927939140
h= 0.05000: f(1.0000000000) = 2.3795619396

为了探索数字的浮点表示的影响,打印出浮点数的真正含义,

print(", ".join("%20.17f"%x for x in np.cumsum(10*[0.1])))

给予

0.10000000000000001,  0.20000000000000001,  0.30000000000000004,  
0.40000000000000002,  0.50000000000000000,  0.59999999999999998,  
0.69999999999999996,  0.79999999999999993,  0.89999999999999991,  
0.99999999999999989

这表明浮点运算后最后尾数位的舍入可能会产生相当违反直觉的结果

【讨论】:

  • 好的,谢谢!我不太明白你所说的浮点格式是什么意思以及你之后所说的(我很少编程,当我做我想做的事情时,我通常会继续前进而不改进代码)。如果你能更详细地解释我将不胜感激。
  • @DaniBaba,通过重复将 h 添加到 x_n,您可能会得到小的舍入错误,导致检查 x_n &lt; 1 在不应该通过时通过,从而导致您采取额外的步骤。我建议宁愿将n(时间步数)作为输入,定义h = x_f/n 并使用for loop 而不是while loop。这样,您将始终采取正确的步数。
猜你喜欢
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多