Numpy float128没有给出正确的答案

Numpy float128没有给出正确的答案,numpy,floating-point,precision,ode,solver,Numpy,Floating Point,Precision,Ode,Solver,我用Python创建了一个微分方程求解器Runge Kutta四阶方法。然后,我决定通过将参数mu设置为0并查看它返回的数值解来检查其结果 问题是,我知道这个解应该给出一个稳定的振荡,但是我得到了一个发散解 代码如下所示。我尝试使用numpy float128数据类型从浮点精度解决舍入错误的问题。但解决者总是给我错误的答案 代码是: import numpy as np import pandas as pd from matplotlib import pyplot as plt def f

我用Python创建了一个微分方程求解器Runge Kutta四阶方法。然后,我决定通过将参数mu设置为0并查看它返回的数值解来检查其结果

问题是,我知道这个解应该给出一个稳定的振荡,但是我得到了一个发散解

代码如下所示。我尝试使用numpy float128数据类型从浮点精度解决舍入错误的问题。但解决者总是给我错误的答案

代码是:

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

def f(t,x,v):
  f = -k/m*x-mu/m*v
  return(f)

def g(t,x,v):
  g = v
  return(g)

def srunge4(t,x,v,dt):
  k1 = f(t,x,v)
  l1 = g(t,x,v)

  k2 = f(t+dt/2, x+k1*dt/2, v+l1*dt/2)
  l2 = g(t+dt/2, x+k1*dt/2, v+l1*dt/2)

  k3 = f(t+dt/2, x+k2*dt/2, v+l2*dt/2)
  l3 = g(t+dt/2, x+k2*dt/2, v+l2*dt/2)  

  k4 = f(t+dt/2, x+k3*dt, v+l3*dt)
  l4 = g(t+dt/2, x+k3*dt, v+l3*dt)

  v = v + dt/6*(k1+2*k2+2*k3+k4)
  x = x + dt/6*(l1+2*l2+2*l3+l4)
  t = t + dt
  return([t,x,v])

mu = np.float128(0.00); k = np.float128(0.1); m = np.float128(6)

x0 = np.float128(5); v0 = np.float128(-10)

t0 = np.float128(0); tf = np.float128(1000); dt = np.float128(0.05)

def sedol(t, x, v, tf, dt):
  sol = np.array([[t,x,v]], dtype='float128')
  while sol[-1][0]<=tf:
    t,x,v = srunge4(t,x,v,dt)
    sol=np.append(sol,np.float128([[t,x,v]]),axis=0)
  sol = pd.DataFrame(data=sol, columns=['t','x','v'])
  return(sol)

ft_runge = sedol(t0, x0, v0, tf, dt=0.1)

plt.close("all")
graf1 = plt.plot(ft_runge.iloc[:,0],ft_runge.iloc[:,1],'b')
plt.show()
我是否以错误的方式使用numpy float128?

您在srunge4中混合了k和l与x和v的关联。根据函数关联和最终求和,关联应为v、f、k和x、g、l。在更新方法的各个阶段时,必须遵守这一点

在第4阶段,第一个参数中应该是t+dt。然而,由于t不用于导数计算,因此该误差在这里没有影响

此外,如果在dt=0.1中的默认float64类型中将一个参数设置为float,则会破坏float128计算

包含这些更正和一些进一步简化的代码如下所示

将numpy作为np导入 作为pd进口熊猫 从matplotlib导入pyplot作为plt mu=np.1280.00;k=np.1280.1;m=np.1286 x0=np.1285;v0=np.128-10 t0=np.1280;tf=np.1281000;dt=np.1280.05 def ft、x、v:返回-k*x+mu*v/m def gt、x、v:返回v def srunge4t,x,v,dt:应该是skutta4,Wilhelm Kutta在1901年给出了这个方法 k1,l1=f,g中fg的fgt,x,v 这是基本的修正,x->l,v->k 对于f,g中的fg,k2,l2=fgt+dt/2,x+l1*dt/2,v+k1*dt/2 k3,l3=f,g中fg的fgt+dt/2,x+l2*dt/2,v+k2*dt/2 k4,l4=f,g中fg的fgt+dt,x+l3*dt,v+k3*dt v=v+dt/6*k1+2*k2+2*k3+k4 x=x+dt/6*l1+2*l2+2*l3+l4 t=t+dt 返回[t,x,v] def sedolt、x、v、tf、dt: sol=[[t,x,v]]
为什么你认为这是个问题?关于这个问题,到目前为止,你做了什么来诊断这个问题?你试过把dt变小吗?对于疯狂的物理学家:我使用一个叫做Xnumbers的电子表格插件来解决这个问题的精确副本,它提供了扩展的浮点精度,它给了我mu=0的正确答案,这是一个稳定的非发散振荡。保罗·潘泽:我会试试,尽管我认为这只会加剧问题。我会告诉你的。对于卢兹尔:你提到的问题将使一个完全不同的图形,而不是一个缓慢增加的振荡。关于dv/dt和dx/dt之间的转换,我认为情况并非如此,因为新的Vs和Xs分别由Ks和Ls计算,Ks由F计算,Ls由G计算。或者我在这里遗漏了什么?几乎完全用新的错误分析替换了答案,并进行了测试更正。对于LutzL:谢谢!。我将仔细检查您在原始函数中所做的每个更改,并尝试在我的代码中查找错误源。关于这个名字,是的,是库塔最初提出了这个方法,龙格是一个共同发现者。这里的问题是我的母语是巴西葡萄牙语。要理解我说的话,请将马丁·威廉姓氏中的K改为p,并删除其中一个T。取下这个词,转到谷歌翻译,让它从巴西葡萄牙语翻译成英语,你就会明白了,KKK。我会把我的发现告诉你。TksFor LutzL:为了结束这个问题,是的,你从一开始就是对的。我把x'方程和vs混合在一起,我接受了你的正确答案。对于卢兹尔:顺便说一句,数字甚至不需要是128型。好的旧浮点数足以产生正确的结果。