首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Matlab程序逼近指数函数

Matlab程序逼近指数函数
EN

Stack Overflow用户
提问于 2012-04-23 13:07:20
回答 2查看 8.5K关注 0票数 4

在处理大实数和负实数时,有人知道如何使下面的Matlab代码更准确地逼近指数函数吗?

例如,当x=1时,代码运行良好,当x= -100时,当它接近3.7201e-44时,返回8.7364e+31的答案。

守则如下:

代码语言:javascript
运行
复制
s=1
a=1;
y=1;
for k=1:40
    a=a/k;
    y=y*x;
    s=s+a*y;
end
s

任何帮助都是非常感谢的,干杯。

编辑:

好的,问题如下:

这段代码近似哪个数学函数?(我说指数函数。)当x= 1?(是。)时,会工作吗?不幸的是,当x= -100产生答案s= 8.7364e+31时,使用这个函数。您的同事认为程序中有一个愚蠢的bug,并请求您的帮助。仔细解释行为,并给出一个简单的解决办法,从而产生更好的效果。[您必须建议对上述代码进行修改,否则就会使用它。您还必须检查您的简单修复工作。

因此,我有点理解,当术语之间有16个(或更多)数量级时,这个问题围绕着大量的数字,精度就失去了,但是这个解决方案没有得到解决。

谢谢

编辑:

所以最后我说了这个:

代码语言:javascript
运行
复制
s = 1;
x = -100;
a = 1;
y = 1;
x1 = 1;

for k=1:40
    x1 = x/10;
    a = a/k;
    y = y*x1;
    s = s + a*y;
end

s = s^10;
s

不确定它是否完全正确,但它返回一些很好的近似。

exp(-100) = 3.720075976020836e-044

S= 3.722053303838800e-044

经过进一步的分析(不幸的是提交了赋值),我意识到增加了迭代次数,从而增加了术语,进一步提高了效率。事实上,以下方面的效率甚至更高:

代码语言:javascript
运行
复制
s = 1;
x = -100;
a = 1;
y = 1;
x1 = 1;

for k=1:200
    x1 = x/200;
    a = a/k;
    y = y*x1;
    s = s + a*y;
end

s = s^200;
s

这意味着:

exp(-100) = 3.720075976020836e-044

S= 3.720075976020701e-044

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-23 13:33:41

正如John在评论中指出的那样,循环中有一个错误。Y= y*k线不能满足您的需要。请更仔细地查看系列中exp(x)中的术语。

不管怎么说,我想这就是为什么你被分配了这个家庭作业,来学习像这样的系列并不能很好地收敛到很大的值。相反,您应该考虑如何减少范围。

例如,您可以使用标识吗?

代码语言:javascript
运行
复制
exp(x+y) = exp(x)*exp(y)

对你有利?假设您存储exp(1) =2.7182818284590452353的值..。

现在,如果我要求您计算exp(1.3)的值,您将如何使用上述信息?

代码语言:javascript
运行
复制
exp(1.3) = exp(1)*exp(0.3)

但是我们已经知道exp(1)的值了。实际上,只要稍微考虑一下,就可以将范围缩小到只对abs(x) <= 0.5快速收敛的级数。

编辑:还有第二种方法可以使用相同身份的变化来缩小范围。

代码语言:javascript
运行
复制
exp(x) = exp(x/2)*exp(x/2) = exp(x/2)^2

因此,假设您希望计算大数的指数,也许是12.8。要使它以可接受的速度收敛,在这个简单的系列中需要很多术语,并且会发生大量的减法取消,所以无论如何你都不会得到很好的精度。但是,如果我们认识到

代码语言:javascript
运行
复制
12.8 = 2*6.4 = 2*2*3.2 = ... = 16*0.8

然后,如果你能有效地计算出0.8的指数,那么所期望的值就很容易恢复,也许是通过重复的平方。

代码语言:javascript
运行
复制
exp(12.8)
ans =
          362217.449611248

a = exp(0.8)
a =
          2.22554092849247
a = a*a;
a = a*a;
a = a*a;
a = a*a
          362217.449611249

exp(0.8)^16
ans =
          362217.449611249

请注意,每当您使用这样的方法进行范围缩减时,虽然您可能会因所需的额外计算而引起数值问题,但是由于您的系列的收敛性大大增强,您通常会走在前面。

票数 7
EN

Stack Overflow用户

发布于 2012-04-23 13:18:51

你为什么认为这是错误的答案?看看这个序列的最后一个项,它的大小,告诉我为什么你期望得到一个接近0的答案。

我最初的回答是,舍入错误是问题所在。这将是这个基本方法的一个问题,但为什么你认为40是足够的适当的数学术语(相对于计算机浮点算术)答案。

40/ 40!~= 10^31。

木片有正确的想法与范围缩小。这是人们用来快速实现这类功能的典型方法。一旦弄清楚了这一点,就可以处理交替序列的舍入错误,方法是在循环中求和相邻的项,并以k=1:2: 40 (例如)为步长。这在这里是行不通的,直到你使用木片的想法,因为对于x= -100,总和增长了很长一段时间。为了保证中间项正在缩小,您需要使用x<1,这样重写就可以了。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10281150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档