Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 简单迭代算法_C++_C_Algorithm_Math - Fatal编程技术网

C++ 简单迭代算法

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(

如果我们得到一组非线性方程系数和某个范围,我们如何在给定范围内找到方程的根

这个方程式是

所以系数数组就是a的数组。假设方程是

然后系数数组是
{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方程..:/