matlab画指数函数曲线
说明 这个问题和另外两个问题(编号2051722037141864067、1638082848257894860)基本上是重复的,我已经在那两个问题做了回答,主要原因是匿名函数f0在x比较大、s比较小的情况下会出现非数NaN,导致计算失败。
更具体的分析与解决方法这里不再重复,感兴趣的请自行查阅(因度娘经常抽风,就不贴链接了,把编号的数字复制替换本问题的地址中question后面的那一串数字即可)。
这里再对两个问题做进一步探讨:一是对出现NaN的原因做更深入分析,二是把积分下限换成0.1的误差分析。
1、结果中出现NaN的原因 之前分析过(参见问题2051722037141864067),之所以不能画图,归根到底是由于f0在某些条件下计算结果出现NaN引起的,而NaN又是由于指数项为0、Bessel函数为无穷大导致的。
■ 对于指数函数exp(-x),在什么条件下结果为0?负指数函数是x的减函数,从数学的角度来说,函数值会逐渐衰减趋近于0,但只要x是有限值,函数值就不真正为0。
但从数值在计算机内的表示来说,双精度浮点数只有8个字节,其表示精度与范围都是有限的,可以判断,x为某个有限值的时候,函数值就会小于最小的正浮点数,也就是数值意义上0。
最小的正浮点数可以用realmin获得,但请注意,这个是所谓规格化(normalized)浮点数,而不是最小的浮点数,最小的浮点数是eps(realmin)(或eps*realmin):>> realminans = 2.225073858507201e-308>> eps(realmin)ans = 4.940656458412465e-324所谓normalized,是指大于该浮点数的运算能够保证精度,一旦小于realmin,被称为IEEE "denormal",不能再保证运算精度。
例如:>> eps(realmin)/2ans = 0>> eps(realmin)/1.99ans = 4.940656458412465e-324我们看到,这个最小的浮点数除以1.99仍然等于其自身,除以2则等于0。
事实上,这个数的浮点数表达只有最后一个bit是1,其它63bit都是0,一旦除以2或更大的数,就会得到全0的八个字节,也就是0。
了解了最小的浮点数,也就可以知道使得exp(-x)数值上达到0的x值了:>> x=-log(eps(realmin))+log(2)x = 745.1332>> exp(-x)ans = 4.9407e-324>> exp(-745.1333)ans = 0也就是说,这个数稍大于745。
■ Bessel函数什么条件下为无穷大?这个有点遗憾,由于Bessel函数不像exp那样有逆函数可用,使得besseli(0,x)为无穷大的x我只能通过试探大致确定在700-701之间:>> besseli(0,700)ans = 1.5296e+302>> besseli(0,701)ans = Inf当然,可以通过进一步的试探确定更多的有效数字:>> besseli(0,700.9217936944459)ans = 3.8426e+302 >> besseli(0,700.921793694446)ans = Inf ■ 函数避免出现NaN的条件 指数项包括两部分,仅以其中一项为例(未包含负号):ezplot(@(v)(log(v) - u).^2./(2*d0),[0 0.1]) 可以看到,在v比较小时,仅此一项就会让负指数函数的值为0。
另外一项对应的指数也是负数,对应的函数值小于1。
可以通过下面的方法大致看到 ezmesh(@(v,x) -((log(v) - u).^2./(2*d0))-(k +1)*x.^2./v.^2,[0 0.1 0 15])zlim([-750 0])view(0,90) 空白区域即意味着指数小于-750,也就是函数值为0。
可见,指数项除了在小部分区域外,大多数条件下的函数值为0,这样,为了避免出现0*Inf,重点在于防止Bessel函数出现无穷大的值。
而即使指数部分不为0,一旦Bessel函数值为Inf,两项相乘的值为Inf,计算结果同样没有意义。
看一下Bessel函数的变量:ezplot(@(v,x) 2*x*sqrt(k*(k+1))./v - 700,[0 0.1 0 50]) axis auto 图中曲线的含义是,当v取某个值的时候,x只有小于特定值,Bessel函数才为有限值。
这个值大约是对应v=0.01,x=4.04;v=0.1,x=40.4,也就是说,对于v=0.01,只能计算大约x 这个结论和之前的分析吻合。
另一方面,我们可以看到,如果只需要画x=0~15区间的积分函数,可以取积分下限为0.04。
2、把积分下限换成0.1的误差分析 按照问题1638082848257894860的分析,把积分下限进行微调成0.1,对于大部分的函数值没有影响。
现在具体看看误差有多大。
由于只是对积分限进行微调,所以需要考虑的只是被积变量v在0~0.1区间f0函数的情况。
这里按照sigma=1来分析(如果按照本题的s分析,几乎没有误差,这一点也可以在问题1638082848257894860里面的曲线看到)。
画出x取不同值的f0-v曲线:ezplot(@(v)f0(v,0),[0 0.1])hold onezplot(@(v)f0(v,0.01),[0 0.1])ezplot(@(v)f0(v,0.05),[0 0.1])ezplot(@(v)f0(v,0.1),[0 0.1])axis auto 可以看到,x=0对应的曲线值是最大的(应该可以从理论上证明),但最大值也是有界的。
对积分下限进行微调导致的误差不会超过这部分积分再乘一个相应的系数。
限于时间精力,这部分的分析未能进一步深入。
写了也没几个人看,就先这样吧。
最后,对积分下限取0.01和0.1的误差进行比较:x = 0:0.01:0.5;df = arrayfun(@(x)integral(@(v)f0(v,x),0.01,inf),x) - arrayfun(@(x)integral(@(v)f0(v,x),0.1,inf),x);f = (2*(k+1)*exp(-k)*x.*df)./(sqrt(2*pi*d0));plot(x,f,'r'); 这也和之前分析的吻合,即只在x比较小的区间(大约0.2)才有一定误差。
而取0.001和0.01的误差更小:结束语 花费好几个小时写的分析,很大程度上和解决楼主所提问题本身已经没有太大关系,只是为了探究使用...
用c++语言 如何画出以e为底的指数函数曲线 如函数y=exp(
void drawExp(HWND hWnd){static RECT rc; if(rc.right==0) GetClientRect(hWnd,&rc); static float w=rc.right, h=rc.bottom, xo=w/2-w/4, yo=h/2+h/4;HDC hdc=GetDC(hWnd);SetGraphicsMode(hdc,GM_ADVANCED); SetMapMode(hdc, MM_LOENGLISH); SetViewportOrgEx(hdc,xo,yo,0L); MoveToEx(hdc,-w/2 +140,0,0L); LineTo(hdc,w, 0); MoveToEx(hdc,0,-h/2+80,0L); LineTo(hdc,0,h/2+ 80); float r=100; float x=-w/2 +160, y=0; xo=x; yo=exp(-x/200)*r; MoveToEx(hdc,xo,yo,0L); float dx=1;do{x+=dx; y=exp(-x/200)*r; LineTo(hdc,x,y); xo=x, yo=y; }while(xReleaseDC(hWnd,hdc); }
Matlab指数拟合问题:谁能帮我看看为什么画出来的图像函数部分是一...
你的代码没错,你要拟合的曲线是 f=a(1)+(-a(1)+a(2))*exp(-a(3)*x); 问题就出在exp(-a(3)*x)上 ,由于x的值都很大,因此exp(-a(3)*x)在超过了matlab的最小数,因此matlab显示的是0。
所以当你用拟合的曲线计算在x出的值时,都等于a(1)了,因为后面的等于零。
因此你画出的图像就是直线了。
我试了一下确实如此。
>> exp(-1790)ans = 0 还有个原因,即使把你的x除以100也会得到一条直线,因为这样的x使得(-a(1)+a(2))*exp(-a(3)*x)的值很小>> xx = Columns 1 through 10 17.9000 18.0000 18.1000 18.2000 18.3000 18.4000 18.5000 18.6000 18.7000 18.8000 Columns 11 through 20 18.9000 19.0000 19.1000 19.2000 19.3000 19.4000 19.5000 19.6000 19.7000 19.8000 Columns 21 through 22 19.9000 20.0000>> (-a(1)+a(2))*exp(-a(3)*x)ans = 1.0e-005 * Columns 1 through 10 -0.1578 -0.1428 -0.1292 -0.1169 -0.1058 -0.0957 -0.0866 -0.0784 -0.0709 -0.0642 Columns 11 through 20 -0.0581 -0.0525 -0.0475 -0.0430 -0.0389 -0.0352 -0.0319 -0.0288 -0.0261 -0.0236 Columns 21 through 22 -0.0214 -0.0193由于a(1)=94.7727,与上述值比起来要大很多 ,因此加起来还是等于94.7727。
>> ans+94.7727ans = Columns 1 through 10 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 Columns 11 through 20 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 94.7727 Columns 21 through 22 94.7727 94.7727 这是不是意味着matlab出错呢?不是的,如果我们换成长格式,让matlab更加精确,就可以看出差别了。
format long>> ansans = Columns 1 through 5 94.772698421642701 94.772698571843264 94.772698707750351 94.772698830724153 94.772698941995472 Columns 6 through 10 94.772699042677914 94.772699133779156 94.772699216210967 94.772699290798357 94.772699358287809 Columns 11 through 15 94.772699419354808 94.772699474610505 94.772699524607916 94.772699569847461 94.772699610781885 Columns 16 through 20 94.772699647820886 94.772699681335155 94.772699711660124 94.772699739099295 94.772699763927278 Columns 21 through 22 94.772699786392565 94.772699806719999这样就很明白了,造成这种问题的原因是值和值之间的相差太小,因此画出的也是直线。
结论是: 必须把x缩小,再使用对数y轴,如图:
转载请注明出处51数据库 » word上画指数函数线