C++ 简单迭代算法
如果我们得到一组非线性方程系数和某个范围,我们如何在给定范围内找到方程的根 这个方程式是 所以系数数组就是a的数组。假设方程是 然后系数数组是C++ 简单迭代算法,c++,c,algorithm,math,C++,C,Algorithm,Math,如果我们得到一组非线性方程系数和某个范围,我们如何在给定范围内找到方程的根 这个方程式是 所以系数数组就是a的数组。假设方程是 然后系数数组是{1,-5,-9,16} 正如谷歌所说,首先我们需要将给定的函数(实际上是方程)变形为其他函数。例如,如果给定的方程是y=f(x),我们应该定义其他函数,x=g(x),然后执行算法: while (fabs(f(x)) > etha) x = g(x); 找出根源 问题是:如何使用系数数组和给定的范围来定义g(x) 问题是:当我这样定义g(
{1,-5,-9,16}
正如谷歌所说,首先我们需要将给定的函数(实际上是方程)变形为其他函数。例如,如果给定的方程是y=f(x)
,我们应该定义其他函数,x=g(x)
,然后执行算法:
while (fabs(f(x)) > etha)
x = g(x);
找出根源
问题是:如何使用系数数组和给定的范围来定义g(x)
问题是:当我这样定义g(x)
时
或
对于给定的方程,x
的任何起始值都将引导我找到第二个方程的根。他们中没有人会给我另外两个(根是{-2.5,1.18,6.05}
,我的代码只给1.18
)
我的代码是这样的:
float a[] = { 1.f, -5.f, -9.f, 16.f }, etha = 0.001f;
float f(float x)
{
return (a[0] * x * x * x) + (a[1] * x * x) + (a[2] * x) + a[3];
}
float phi(float x)
{
return (a[3] * -1.f) / ((a[0] * x * x) + (a[1] * x) + a[2]);
}
float iterationMethod(float a, float b)
{
float x = (a + b) / 2.f;
while (fabs(f(x)) > etha)
{
x = phi(x);
}
return x;
}
#include <iostream>
#include <cmath>
float a[] = { 1.f, -5.f, -9.f, 16.f }, etha = 0.001f;
float f(float x)
{
return (a[0] * x * x * x) + (a[1] * x * x) + (a[2] * x) + a[3];
}
float df(float x)
{
return (3 * a[0] * x * x) + (2 * a[1] * x) + a[2];
}
float newtonMethod(float a, float b)
{
float x = (a + b) / 2.f;
while (fabs(f(x)) > etha)
{
x -= f(x)/df(x);
}
return x;
}
int main()
{
std::cout << newtonMethod(-5,0) << '\n'; // prints -2.2341
std::cout << newtonMethod(0,5) << '\n'; // prints 1.18367
std::cout << newtonMethod(5,10) << '\n'; // prints 6.05043
}
因此,调用iterationMethod()
传递范围{-3,0}
,{0,3}
和{3,10}
将提供三次1.18
数字
我错在哪里?我应该如何行动才能让它正常工作
UPD1:我不需要任何第三方库
UPD2:我需要精确的“简单迭代”算法。更传统的根查找算法之一是。迭代步骤包括找到函数一阶近似的根 因此,如果我们有一个函数“f”,并且位于点
x0
,线性一阶近似值将为
f_x=f'(x0)*(x-x0)+f(x0)
相应的近似根x'
为
x'=phi(x0)=x0-f(x0)/f'(x0)
(请注意,您需要准备好导数函数,但对于多项式,应该很容易获得它)
牛顿方法的优点是易于实现,而且通常速度非常快。糟糕的是,有时它的表现并不好:该方法在具有
f'(x)=0的点上失败,并且在某些函数中的某些输入可能会发散(因此,您需要检查这一点,并在需要时重新启动).您在评论中发布的解释了为什么使用此算法无法找到所有根-它仅在根周围|phi'(x)|<1
时收敛到根。多项式的任何根都不是这样;对于大多数起始点,迭代将围绕中间根反弹,并最终意外地接近它;几乎可以肯定的是,无论它从哪里开始,它都不会与其他根足够接近
要找到所有三个根,您需要一个更稳定的算法,例如(在您链接到的中也有描述)。这也是一种迭代方法;您可以使用迭代x->x-f(x)/f'(x)
找到f(x)
的根。这仍然不能保证收敛,但收敛条件要宽松得多。对于多项式,它可能看起来有点像:
float a[] = { 1.f, -5.f, -9.f, 16.f }, etha = 0.001f;
float f(float x)
{
return (a[0] * x * x * x) + (a[1] * x * x) + (a[2] * x) + a[3];
}
float phi(float x)
{
return (a[3] * -1.f) / ((a[0] * x * x) + (a[1] * x) + a[2]);
}
float iterationMethod(float a, float b)
{
float x = (a + b) / 2.f;
while (fabs(f(x)) > etha)
{
x = phi(x);
}
return x;
}
#include <iostream>
#include <cmath>
float a[] = { 1.f, -5.f, -9.f, 16.f }, etha = 0.001f;
float f(float x)
{
return (a[0] * x * x * x) + (a[1] * x * x) + (a[2] * x) + a[3];
}
float df(float x)
{
return (3 * a[0] * x * x) + (2 * a[1] * x) + a[2];
}
float newtonMethod(float a, float b)
{
float x = (a + b) / 2.f;
while (fabs(f(x)) > etha)
{
x -= f(x)/df(x);
}
return x;
}
int main()
{
std::cout << newtonMethod(-5,0) << '\n'; // prints -2.2341
std::cout << newtonMethod(0,5) << '\n'; // prints 1.18367
std::cout << newtonMethod(5,10) << '\n'; // prints 6.05043
}
#包括
#包括
浮点a[]={1.f,-5.f,-9.f,16.f},etha=0.001f;
浮点数f(浮点数x)
{
返回(a[0]*x*x*x)+(a[1]*x*x)+(a[2]*x)+a[3];
}
浮动df(浮动x)
{
返回(3*a[0]*x*x)+(2*a[1]*x)+a[2];
}
浮动牛顿法(浮动a、浮动b)
{
浮动x=(a+b)/2.f;
而(fabs(f(x))>etha)
{
x-=f(x)/df(x);
}
返回x;
}
int main()
{
std::不能很冗长地重复更新的问题:只有手工制作的“简单迭代”方法是必需的。没有任何第三方库。只需手工编写少量代码。数值算法可能会因您使用的函数而异。您对输入函数了解多少?多项式是什么?它们可以区分吗?一次?两次?@Ernest Friedman Hill:?我看到的唯一相似之处是,两者都在询问t方程..:/