用C++解迭代方程(自洽方程)

一、题目回顾

部分题目图片如下:

二、题目解读

第一问只需要把迭代方程用c++代码表示出来,存储在数据文件里,再用gnuplot绘图即可

重点解释第二问和第三问

2)求解给定 K 和 c 时的稳定不动点

  • 迭代序列的长度:选择n={10}^6迭代。
  • 收敛判据:设置一个非常小的数 ϵ=10^{-10} 作为收敛的判断标准。
  • 初始值:迭代序列的初始值 𝑥0可以从区间 [0,1]内随机选择。
  • 步长:迭代步长 Δ𝑥(0)=0.1
  • 计算:对于每个初始值 x0​,执行迭代计算直到满足收敛条件 ∣𝑥𝑛+1−𝑥𝑛∣<𝜖,或者达到迭代次数 n。
  • 输出:输出每个初始值对应的迭代序列 α(n) 以及最终判断是否收敛。

可以将每个初始值的迭代序列及其是否收敛的结果打印到控制台,或者将它们保存到文本文件中。

(3)给定 K 后,输出给定范围内 c 对应的所有稳定不动点

  • 参数 K:给定 K 的值(K=2 和 K=3)。
  • 参数 c 的范围:考虑 c 在区间 [0,10]内。
  • 步长 Δc:设置 c 的步长为 0.1。
  • 计算:对于每个 c 的值,使用问题(2)中的迭代方法来计算稳定不动点。
  • 去重:由于相邻的不动点可能非常接近,您可以使用数据结构(例如集合或列表)来存储已计算得到的不动点。当新的不动点与已有的不动点非常接近(例如差的绝对值小于50×ϵ)时,可以将它们视为同一个不动点。
  • 输出:输出 K 和 c 对应的所有不同稳定不动点,以及它们随着 c 的变化曲线。(用gnuplot绘制)

三、具体代码实现

以下为第一问代码+gnuplot代码+图像
//第一问 
#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
#include <string>
#include <sstream> 
using namespace std;
int cheng(int k){
	int result=1;
	while(k>0){
		result*=k;
		k--;
	}
	return result;
};
double f(double x, int k, double c) {
	double sum=0;
    while (k-2>=0){
    	sum += pow(c*x,k-2)/cheng(k-2);
    	k--;
    	
	}
	return 1-exp(-c*x)*sum;
} ;

int main() {
    const int K = 2;
    double c_values[] = {0.5, 1.0, 1.5};
    const int c_values_size = sizeof(c_values) / sizeof(c_values[0]);
    const double start_x = 0.0;
    const double end_x = 1.0;
    const double step = 0.001;

    for (int i = 0; i <= c_values_size; ++i) { // 确保使用的是 <= 而不是 <=
        double c = c_values[i];
        std::ostringstream stream; // 创建 ostringstream 对象
        stream << "f_x_values_c_" << c << ".txt"; // 构造文件名字符串
        std::string filename = stream.str(); // 转换为 std::string

        std::ofstream outfile(filename.c_str()); // 使用 c_str() 转换为 C 风格字符串
        for (double x = start_x; x <= end_x; x += step) {
            double f_x = f(x, K, c); // 假设 f 是已定义的函数
            outfile << x << " " << f_x << std::endl; // 使用流插入运算符
        }
        outfile.close();
    }

    return 0;
}

注:曲线与y=x相交的点即为方程的不动点

第二问代码如下
//第二问
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
int cheng(int k){
	int result=1;
	while(k>0){
		result*=k;
		k--;
	}
	return result;
};
//计算迭代方程的函数 
double f(double x, int k, double c) {
	double sum=0;
    while (k - 2>=0){
    	sum += pow(c*x,k-2)/cheng(k-2);
    	k--;
	}
	return 1-exp(-c*x)*sum;
} ;
int main() {
    const int K = 2; // 给定的 K 值
    const double c = 0.5; // 给定的 c 值
    const int n = 1e6; // 迭代次数
    const double epsilon = 1e-10; // 收敛判据
    const double start_x = 0.1; // 起始 x 值
    const double step = 0.1; // x 的步长

    cout.precision(10); // 设置输出精度

    for (double x = start_x; x <= 1.0; x += step) {
        double x_current = x;

        for (int i = 0; i < n; ++i) {
            x_current = f(x_current, K, c); // 进行迭代

            // 检查是否收敛
            if (abs(x_current - x_current * (1 - x_current)) < epsilon) {
                cout << "初始值 " << x << " 在迭代 " << i << " 次后收敛于 " << x_current << endl;
                break; // 收敛则退出循环
            }
        }
    }

    return 0;
}

注:不知道这一问是不是我理解错了,输出收敛序列不就是输出x嘛

第三问代码+图像如下
//第三问 
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <limits>
#include <set>
using namespace std;
int cheng(int k){
	int result=1;
	while(k>0){
		result*=k;
		k--;
	}
	return result;
};
//计算迭代方程的函数 
double f(double x, int k, double c) {
	double sum=0;
    while (k - 2>=0){
    	sum += pow(c*x,k-2)/cheng(k-2);
    	k--;
	}
	return 1-exp(-c*x)*sum;
} ;
set<double> found_fixed_points;

double calculate_fixed_point(double c, int K, int max_iterations, double epsilon) {
    double x = 0.1; // 随机初始化 x
    double x_new = x;

    for (int i = 0; i < max_iterations; ++i) {
        x_new = f(x, K, c);
        if (std::abs(x_new - x) < epsilon) {
            return x_new;
        }
        x = x_new;
    }
    return x; // 如果没有收敛,则返回最后的 x 值
}

int main() {
    const int K = 3; // 可以更改 K 的值来计算不同的不动点
    const double start_c = 0.0;
    const double end_c = 10.0;
    const double step_c = 0.1;
    const int max_iterations = 1e6;
    const double epsilon = 1e-10 * 50; // 收敛精度

    std::ofstream outfile("fixed_points.dat");
    for (double c = start_c; c <= end_c; c += step_c) {
        double fixed_point = calculate_fixed_point(c, K, max_iterations, epsilon);
        // 检查是否已经计算过相邻的不动点
        if (found_fixed_points.find(fixed_point) == found_fixed_points.end()) {
            outfile << c << " " << fixed_point << std::endl;
            found_fixed_points.insert(fixed_point);
        }
    }
    outfile.close();

    std::cout << "计算完成,结果保存到 fixed_points.dat" << std::endl;
    return 0;
}

注:k=3时的图像的不动点几乎都在0.9往上,应该是精度设置的问题?

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值