一、题目回顾
部分题目图片如下:
二、题目解读
第一问只需要把迭代方程用c++代码表示出来,存储在数据文件里,再用gnuplot绘图即可
重点解释第二问和第三问
2)求解给定 K 和 c 时的稳定不动点
- 迭代序列的长度:选择n=
迭代。
- 收敛判据:设置一个非常小的数 ϵ=
作为收敛的判断标准。
- 初始值:迭代序列的初始值 𝑥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往上,应该是精度设置的问题?