我试图在函数中找到所有根[f(x)= 0]。我目前的解决方案只有在它们间隔足够且不会相互干扰的情况下才有效。 (例如,它适用于x ^ 2 - 2)
bool numberIsCloseToZero(num number){
return (num.parse(number.abs().toStringAsFixed(1)) == 0.0) ? true : false;
}
List<num> calculateRoots(String function){
num eval = 0.0;
List<num> roots = [];
for (num x = -10; x < 10; x += 0.1){
eval = calculateYOfX(function, x);
if (numberIsCloseToZero(num.parse(eval.toStringAsFixed(2)))){
roots.add(x);
}
}
return roots;
}
显然,这是由于我的四舍五入。 (例如,x ^ 2的根的周围值太接近于零,因此它假设它们也是根)。你是否认为我应该通过实际解决方程而不是&#34;暴力强迫&#34;根源?
由于
答案 0 :(得分:3)
如果您能找到分析解决方案 - 请使用它。低阶多项式方程(如提到的x^2 - 2
)是可能的。
一般情况下 - 你必须学习数值方法 - 在这种情况下,root finding。
答案 1 :(得分:1)
您需要对允许的功能进行一些限制,否则您没有希望。
例如,没有任何限制,您不能保证在给定的时间间隔内只有有限数量的值(考虑f(x)=sin(x)
),或者甚至是有限数量的值(考虑{{1 })。甚至无限连接的零(f(x)=x sin(1/x)
)
这些病例甚至不被认为是特别病态的数学函数。
如果你愿意沿着这条道路前行,要求你的功能几乎无处不在,平稳,连续,并且有限的一阶和二阶导数,那么我想你可能想出一个相对简单的算法,保证您在给定的有限区域内获得全零。
(我会寻找一种基于细分的算法,该算法递归地分割区域并确定每个区间的严格界限。)
我们可以导出一个示例算法,用于何时导数由已知常数f(x) = max(0,x)
限定。请注意,如果我们在某个时间|f'(x)| < D
评估f
,那么对于任何其他点p
,我们可以显示p+d
。
使用此功能,我们可以在f(p) - |d| D < f(p+d) < f(p) + |d| D
区间内考虑根查找 - 我们可以将[A,B]
写成[p-d, p+d]
,p=(A+B)/2
。在中间点示例d=(B-A)/2
以获得f
。最小值f(p)
可以采用f
的间隔,最大值为f(p) - d D
。如果f(p) + d D
等同于f(p)-d D <= 0 <= f(p) +d D
,则我们只能在此区间内拥有根。
如果我们已完成|f(p)| < d D
中的根目录,则我们会重复[A,B]
和[A,p]
两半。 (在[p,B]
)