不动点迭代算法

今天有个小朋友向我提出了一个「了不起」的问题。

一个有趣的现象

打开一个没有 Bug 的计算器,任意输入一个数值 \(x\),然后找到函数 \(sin(x)\) 或者 \(cos(x)\) ,连续点击这个函数若干次,你会发现一个有趣的现象:无论初始的 \(x\) 为多少,最后的值总是接近某一个数值(这些数值在某个精度范围内是相等的)。\(sin(x)\) 最后总为 \(0\) ,\(cos(x)?\) 最后为 0.73 或者 0.99 (取决于你的计算器是否开启弧度制)。

从数学的角度来看,实际上就是:定义 \(f^1(x) = f(x), f^2(x)=f(f(x)), f^{n}(x)=f(f(f(...f(x))))\) ,\(n\) 个 \(f\) 进行复合函数运算,求 \(\lim\limits_{n \rightarrow \infty} f^{n}(x)\) 。

显然,这道证明题我不会??。

万能的搜索引擎

虽然我不会证明,但是找一下是什么知识点还是挺简单的。查了一圈回来,发现这其实是「数值分析」中的 不动点方程 。上述证明题,\(\lim\limits_{n \rightarrow \infty} f^{n}(x)\) 的值实际上是 \(x = f(x)?\) 的根。这个方程用「零点定理」,写一个 while-loop 就出来了,所以就不说了。

算了,还是说一下吧,反正闲着也是闲着。设 \(g(x) = x - \cos(x)?\),显然 \(g(0) \cdot g(1) < 0?\),\(g(x)?\) 为增函数,因此在 \((0,1)?\) 上有 1 个零点。

#include <iostream>
#include <cmath>
using namespace std;
double func(double x)
{
    return x - cos(x);
}
int main()
{
    const double eps = 1e-8;
    double l = 0, r = 1;
    while ((r - l) >= eps)
    {
        double mid = (l + r) / 2;
        func(mid) > 0 ? (r = mid) : (l = mid);
    }
    printf("%.8lf %.8lf\n", l, r);
}

不动点迭代算法

这是扩展阅读部分,因为这篇文章看起来篇幅不太够,所以就凑点字数,反正看 blog 的人大多数都是一些「无聊的人」O(∩_∩)O 。

不动点迭代 (Fixed Point Iteration) ,用于求解某些非线性函数 \(f(x)?\) 的零点,也就是解方程 \(f(x) = 0?\) 。那么这个「不动点迭代算法」到底有什么用呢?

比如我想求 \(f(x) = 1 + 0.5 \sin{x} - x?\) 的根,那么可以进行如下变换:
\[
f(x) = 0 \quad \Rightarrow \quad x = 1+0.5\sin{x}
\]
然后令 \(g(x) = 1+0.5 \sin {x}\) ,对 \(x_{i+1} = g(x_i)\) 执行迭代若干次,就可以得到原方程的根 \(x_n\) 。

有这个「不动点迭代」法,求根就可以简单一点(虽然比「二分法」没简单多少??)。

double func(double x)
{
    return 1 + 0.5 * sin(x);
}
int main()
{
    srand(time(NULL));
    double x = rand();
    for (int i = 0; i < 10; i++)
        x = func(x);
    printf("%.10lf", x);
}

但这个算法其实对于 \(g(x)\) 来说是有条件的,并不是所有的方程都适用。如果对于方程 \(x = 2x^3-1, g(x)=2x^3-1\) 执行上面的算法,我们是得不到正确的答案 \(x=1\) 的。

Aside
设迭代函数 \(g(x)\) 在 \([a,b]\) 上连续,且满足:

  • 当 \(x \in [a,b]\) 时,\(a \le g(x) \le b\)
  • 存在一正数 \(L\) 满足 \(0 < L < 1\),且 \(\forall{x} \in [a,b]\) 均有 \(|g^{'}(x)| \le L\)

则方程 \(x = g(x)\) 在 \([a,b]\) 上有唯一解 \(x_n\) 。对于任意的初值 \(x_0 \in [a,b]\) ,均可通过 \(x_{i+1} = g(x_i)\) 迭代求得 \(x_n\) 。

详细的证明请看这里

总结

实际上我并没有解决这个小朋友的疑问(因为??也??懂怎么证明),但是至少我又水了一篇 blog,打发了两个小时的无聊时间。唉,什么时候才动手搞毕业设计呢,真是有够堕落的。

众所周知,百度是一家大型广告公关公司,附带高质量的站内搜索引擎??,但有一说一,百度文库确实挺好用的??,特别是找课件看,找期末题库。

原文地址:https://www.cnblogs.com/sinkinben/p/12422931.html

时间: 2025-01-17 14:22:20

不动点迭代算法的相关文章

ListSet_对半搜索的迭代算法

递归函数效率低, 常使用相应的迭代算法. mid, left, right均为元素下标, 如果当前表不为空, 则令x与l[mid]比较. 若两者相等, 则搜索成功. 若前者小于后者, 则继续查找左半部分, 否 则查找右半部分. 下标范围分别为[left, mid - 1], [mid + 1, right]. 如果当前搜索表为空表, 搜索失败返回NotPresent. 实现代码: #include "iostream" #include "cstdio" #incl

转载 迭代算法实现开平方

迭代是数值分析中通过从一个初始估计出发寻找一系列近似解来解决问题(一般是解方程或者方程组)的过程,为实现这一过程所使用的方法统称为迭代法(Iterative Method). 一般可以做如下定义:对于给定的线性方程组x=Bx+f(这里的x.B.f同为矩阵,任意线性方程组都可以变换成此形式),用公式x(k+1)=Bx(k)+f(括号中为上标,代表迭代k次得到的x,初始时k=0)逐步带入求近似解的方法称为迭代法(或称一阶定常迭代法).如果k趋向无穷大时limt(k)存在,记为x*,称此迭代法收敛.显

多线性方程组迭代算法——Jacobi迭代算法的Python实现

多线性方程(张量)组迭代算法的原理请看这里:若想看原理部分请留言,不方便公开分享 Gauss-Seidel迭代算法:多线性方程组迭代算法——Gauss-Seidel迭代算法的Python实现 import numpy as np import time 1.1 Jacobi迭代算法 def Jacobi_tensor_V2(A,b,Delta,m,n,M): start=time.perf_counter()#开始计时 find=0#用于标记是否在规定步数内收敛 X=np.ones(n)#迭代起

多线性方程组迭代算法——Gauss-Seidel迭代算法的Python实现

多线性方程组(张量)迭代算法的原理请看这里:原理部分请留言,不方便公开分享 Jacobi迭代算法里有详细注释:多线性方程组迭代算法——Jacobi迭代算法的Python实现 import numpy as np import time 1.1 Gauss-Seidel迭代算法 def GaussSeidel_tensor_V2(A,b,Delta,m,n,M): start=time.perf_counter() find=0 X=np.ones(n) d=np.ones(n) m1=m-1 m

flink 实现ConnectedComponents 连通分量,增量迭代算法(Delta Iteration)实现详解

1.连通分量是什么? 首先需要了解什么是连通图.无向连通图.极大连通子图等概念,这些概念都来自数据结构-图,这里简单介绍一下. 下图是连通图和非连通图,都是无向的,这里不扩展有向图: 连通分量(connected component):无向图中的极大连通子图(maximal connected subgraph)称为原图的连通分量. 极大连通子图: 1.连通图只有一个极大连通子图,就是它本身.(是唯一的) 2.非连通图有多个极大连通子图.(非连通图的极大连通子图叫做连通分量,每个分量都是一个连通

解方程——不动点迭代

定义:如果g(r)=r,那么实数r是函数g的一个不动点. 如果我们有方程f(x)=0,表示为不动点问题时,有:g(x)=x   (注:f(x)=g(x)-x) 不动点r是方程f(x)=0的一个根,几何表示为y=g(x)与y=x的交点就是不动点r 算法分析:x0 = 初始设定值 x1 = g(x0) x2 = g(x1) x3 = g(x2) ...    ... x(k+1) = g(x(k)) 直到收敛至g(r) = g(lim x(i)) = lim x(i+1) = r matlab代码实

迭代算法

迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果.每一次对过程的重复称为一次"迭代",而每一次迭代得到的结果会作为下一次迭代的初始值. 举例: 1 1 2 3 5 8 13 21 ... 从第三个值开始,每个值都是前两个值的和   特征就是每次迭代的结果都可能作为后一次或者后几次迭代的输入值. C# 实现,写一个函数迭代实现求第N个值是多少? 1 /// <summary> 2 /// 迭代 3 /// </summary> 4 class Iter

递归算法与迭代算法的区别

举个例子:我想求1+2+3+4+..+100的值.迭代的做法:从1到100,顺着往下累加.1+2=3,3+3=6,6+4=10,10+5=15…… 程序表示, int i=1,sum=0; while(i<=100){ sum = sum +i; }递归的做法:我要求1到100的累加值,如果我已经得到1到99的累加值,将这个值加上100就是1到100的累加值:要得到1到99的累加值,如果已经得到1到98的累加值,将这个值加上99,就是1到99的累加值……最后我要得到1到2的累加值,我如果得到1自

迭代算法求平方根

#include<stdio.h>#include<math.h>void main() {      double a,x0,x1;    printf("input a:\n");    scanf("%lf",&a);    if(a<0)printf("ERROR!\n");    else     {          x0=a/2;         x1=(x0+a/x0)/2;        d