麦克劳林级数的函数逼近
我需要大约 (1-x)^0.25 给定的精度(0.0001 例如)。我正在使用在维基百科上找到的扩展为 (1+x)^0.25。当当前表达式小于精度时,我需要停止近似。
long double s(long double x, long double d) {
long double w = 1;
long double n = 1; // nth expression in series
long double tmp = 1;
// sum while last expression is greater than accuracy
while (fabsl(tmp) >= d) {
tmp *= (1.25 / n - 1) * (-x); // the next expression
w += tmp; // is added to approximation
n++;
}
return w;
}
不介意长双n。 :P 当我不检查当前表达式的值而是计算 1000 个或更多表达式时,这很有效。函数的定义域是<-1;1> s() 可以很好地计算 x 在 <-1;~0.6> 中的近似值。参数越大,计算误差越大。从 0.6 开始就超过了精度。
我不确定问题是否足够清楚,因为我不太懂英语数学。问题是 while 条件出了什么问题以及为什么函数 s() 不能正确近似。
编辑: 问题基本解决了。当 x>0 时,我必须从 1 中减去连续表达式的绝对值。
if (x<0)
w += tmp;
else
w -= fabsl(tmp);
之后精度会提高很多(当然,fox x>0)。冗余错误源于长时间的双重不准确。就这样。不管怎样,谢谢你们。
I need to approx (1-x)^0.25 with given accuracy (0.0001 e.g.). I'm using expansion found on Wikipedia for (1+x)^0.25. I need to stop approximating when current expression is less than the accuracy.
long double s(long double x, long double d) {
long double w = 1;
long double n = 1; // nth expression in series
long double tmp = 1;
// sum while last expression is greater than accuracy
while (fabsl(tmp) >= d) {
tmp *= (1.25 / n - 1) * (-x); // the next expression
w += tmp; // is added to approximation
n++;
}
return w;
}
Don't mind long double n. :P This works well when I'm not checking value of current expression but when I'm computing 1000 or more expressions. Domain of the function is <-1;1> and s() calculates approximation well for x in <-1;~0.6>. The bigger the argument is the bigger is the error of calculation. From 0.6 it exceeds the accuracy.
I'm not sure if the problem is clear enough because I don't know English math language well. The thing is what's the matter with while condition and why the function s() doesn't approximate correctly.
EDIT:
Problem mostly solved. When x>0 I have to substract absolute value of consecutive expressions from 1.
if (x<0)
w += tmp;
else
w -= fabsl(tmp);
After that accuracy increases a lot (fox x>0 of course). Redundant error stems from long double inaccuracy. That's all. Thanks anyway to you guys.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试画函数图
even in close x range such as [-0.5;0.5] you will get something like:
这意味着您的二项展开式实现不稳定。随着 x 距离零越来越远,级数必须包含越来越多的项以达到给定的精度。但在当前的扩展实现中这样做会导致发生灾难性取消(某些浮点错误累积机制) )。尝试阅读我给出的有关如何设计数值稳定算法的链接。
顺便说一句,感谢您提出非常有趣的问题!
Try drawing graph of function
even in close x range such as [-0.5;0.5] you will get something like:
This means that your binomial expansion implementation is unstable. As x gets further and further from zero - series must include more and more terms for given accuracy. But doing so in current expansion implementation causes Catastrophic cancellation to occur (some floating point error accumulation mechanism). Try reading my given link on how to design numerically stable algorithm.
BTW, thanks for really interesting problem !
你的问题是,虽然你的算法的迭代部分很好,但终止并不是你想象的那样。
当计算无限和时,您使用的泰勒级数展开是精确的。但是,您无法评估该无限总和并且正在截断。
我想您假设当 tmp 变得小于您想要的容差时,那么 w 中的误差也小于该容差。
然而,事实并非如此。每次迭代的误差是剩余项的无限和。它是您丢弃的无数项的总和。其中第一个,即终止时的 tmp 值,可能小于您的容忍度,但它们的总和可能大于您的容忍度。
当 (-x) 为负数时,您恰好可以逃脱惩罚,因为
tmp
的交替符号对您有利。当 (-x) 为正数时,当x
接近零时,您就可以逃脱惩罚。然而,我不相信有一种简单的方法可以提出一个简单的通用停止标准。你必须能够对你要放弃的条款设定一些界限。现在这变成了一个数学问题而不是一个编程问题。
Your problem is that whilst the iteration part of your algorithm is fine, the termination is not what you think it is.
The Taylor series expansion you are using is exact when the infinite sum is evaluated. However, you cannot evaluate that infinite sum and are truncating.
I suppose you are assuming that when
tmp
becomes smaller than your desired tolerance, then the error inw
is also less than that tolerance.However, this is not true. The error, at each iteration is the infinite sum of the remaining terms. It is the sum of the infinite number of terms that you are throwing away. The first one of these, the value of
tmp
at the point of termination, may be less that your tolerance, but the sum of them all may be greater than your tolerance.You happen to get away with it when (-x) is negative because the alternating sign of
tmp
works in your favour. And when (-x) is positive you get away with it whenx
is close to zero.However, I'm not convinced there is an easy way to come up with a simple general purpose stopping criteria. You'd have to be able to put some bounds on the terms which you are throwing away. This now becomes a mathematical problem rather than a programming problem.