- 积分
- 7
- 注册时间
- 2002-9-10
- 仿真币
-
- 最后登录
- 1970-1-1
|
楼主 |
发表于 2009-12-28 20:05:14
|
显示全部楼层
来自 山东淄博
原贴主到了,这样讨论问题比较方便。
问题图片我又更新了,积分式中的τ实际上应是t?
我优化了Forcal的数值算法,主要是为了提高速度,方法:保存中间变量,用插值法近似取值。
但效果不算太好。求解精度取1e-3,算t=10,m=5需要几分钟的时间,其他的没有尝试。
- //SetTalk[false];
- !SetRealStackMax(1000);
- Rm(t,m:j,s,a,b,h:hVm,iRm,tmax)=
- {
- iRm++, h=0.0005, if[t>=h, h=-0.0005],
- sys::call(2,hVm :t+h,m : &a), //计算s=Vm(t+h,m)
- sys::call(2,hVm :t,m : &b), //计算s=Vm(t,m)
- s=[a-b]/h,
- j=0,(j<=m).while{
- sys::call(2,hVm :t,j : &a), sys::call(2,hVm :t,m-j : &b), //计算a=Vm(t,j), b=Vm(t,m-j)
- s=s+a*b,
- j++
- },
- s-[1-which(m<1,0,1)] //最后返回这个值。看这句有没有问题:取m<1,而不是m<=1
- };
- //Fkappa将返回s的值。mm是模块变量,因调用Rm(t,mm-1)时mm将改变,故用a预先保存,函数返回前恢复mm的值
- Fkappa(t:a,s,i,kappa,x1,x2,y1,y2:mm,_t,_m,tmax,VmArray,iFkappa)=
- { iFkappa++, kappa=0, a=mm,
- i=t/_t*tmax,
- if{VmArray.XSLSF::getrai[a+_m+1,i,0] & VmArray.XSLSF::getrai[a+_m+1,i+1,0], //获得Fkappa(t,m)
- x1=VmArray.XSLSF::getrai(a+_m+1,i,1), y1=VmArray.XSLSF::getrai(a+_m+1,i,2),
- x2=VmArray.XSLSF::getrai(a+_m+1,i+1,1), y2=VmArray.XSLSF::getrai(a+_m+1,i+1,2),
- return[y1+(y2-y1)*(t-x1)/(x2-x1)]
- },
- s=t^(2*kappa)*Rm(t,mm-1), mm=a,
- i=t/_t*tmax, VmArray.XSLSF::setrai[a+_m+1,i,0,1], VmArray.XSLSF::setrai[a+_m+1,i,1,t], VmArray.XSLSF::setrai[a+_m+1,i,2,s], //保存Fkappa(t,m)
- s
- };
- Vm(t,m:h,kappa,s,i,x1,x2,y1,y2:VmArray,_t,tmax,mm,hFkappa,iVm)=
- {
- iVm++, h=-1, kappa=0,
- if[m<=0,return(t)], if[m==1,return(1/3*h*t^3)],
- i=t/_t*tmax,
- if{VmArray.XSLSF::getrai[m,i,0] & VmArray.XSLSF::getrai[m,i+1,0], //获得Vm(t,m)
- x1=VmArray.XSLSF::getrai(m,i,1), y1=VmArray.XSLSF::getrai(m,i,2),
- x2=VmArray.XSLSF::getrai(m,i+1,1), y2=VmArray.XSLSF::getrai(m,i+1,2),
- return[y1+(y2-y1)*(t-x1)/(x2-x1)]
- },
- s=which(m<=1,0,1)*Vm(t,m-1)+h*{mm=m, XSLSF::fpqg[hFkappa,0,t,1e-3]}, //XSLSF::fpqg即徐士良算法中的连分式积分法
- i=t/_t*tmax, VmArray.XSLSF::setrai[m,i,0,1], VmArray.XSLSF::setrai[m,i,1,t], VmArray.XSLSF::setrai[m,i,2,s], //保存Vm(t,m)
- s
- };
- pert(t)=t-1/3*t^3+2/15*t^5-17/315*t^7;
- main(t,m:k,s:VmArray,_t,_m,tmax,hFkappa,hVm,iRm,iFkappa,iVm)=
- {
- iRm=0, iFkappa=0, iVm=0,
- _t=t, _m=m, tmax=20000, //tmax>=10000,越大越精确
- VmArray=new[rtoi(real_s),rtoi(m+m+2),rtoi(tmax+2),rtoi(3)],
- k=0,(k<=m+m+1).while{
- s=0,(s<=tmax).while{
- VmArray.XSLSF::setrai[k,s,0,0],
- s++
- },
- k++
- },
- hFkappa=HFor("Fkappa"), hVm=HFor("Vm"), //预先获得函数Fkappa和Vm的句柄,函数调用时将用到
- s=0,k=0,(k<=m).while{
- s=s+Vm(t,k),
- k++
- },
- printff{"\r\n结果={1,r,-25.16}, 验证pert(t)={2,r,-25.16}, 函数Rm调用次数{3,i,-8}, 函数Fkappa调用次数{4,i,-8}, 函数Vm调用次数{5,i,-8}",s,pert(t),iRm,iFkappa,iVm},
- delete[VmArray],
- s //返回s
- };
- main[10,3];
- main[10,5];
复制代码
m=3时的验证公式:pert(t)=t-1/3*t^3+2/15*t^5-17/315*t^7;
从t=10,m=3的验证结果看,应该是准确的(t=10,m=5时没有验证公式):
结果=-526669.7208717888 , 验证pert(t)=-526672.5396825398 , 函数Rm调用次数74669 , 函数Fkappa调用次数149094 , 函数Vm调用次数451097
结果=-1206839696.504438 , 验证pert(t)=-526672.5396825398 , 函数Rm调用次数334056 , 函数Fkappa调用次数68015611, 函数Vm调用次数2799112
|
|