У меня есть код на c++ который интерполирует 3 фун...
Создано: 28 мая 2025 г.
Создано: 28 мая 2025 г.
У меня есть код на c++ который интерполирует 3 функции и выводит результаты в файл. Мне надо дополнить программу, чтобы она выводила значения сплайна и функций, а также их первых и вторых производных специальным образом.
Тот вывод, что уже есть в программе оставь, результаты сплайна, функций, а также их разность должны записываться в файлы function(1,2,3)_values.txt в таком формате j xj Fj Sj Fj-Sj F'j S'j F'j-S'j где j начинается с 1. Значения вторых производных должны выводиться в файлы function(1,2,3)_derivatives.txt в таком формате i x F''(x) S''(x) |F''-S''| где i начинается с 1. Дополни c++ код, чтобы все нужные данные высчитывались если надо и записывались в соответствующие файлы в нужные столбики. В первой строчке каждого файла должна стоять одна из двух строчек, что я привел, для каждой функции есть свои два файла,например, function1_values.txt и function1_derivatives.txt. Вот c++ код
#include <iostream>
#include <vector>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;
struct SplineSegment {
double xi; // левый узел сегмента [x_{i-1}, x_i]
double a, b, c, d; // «левые» коэффициенты
};
// ─────────── функции и их производные ───────────
double f1(double x) { return (x <= 0) ? x * x * x + 3 * x * x : -x * x * x + 3 * x * x; }
double f1p(double x) { return (x <= 0) ? 3 * x * x + 6 * x : -3 * x * x + 6 * x; }
double f1pp(double x) { return (x <= 0) ? 6 * x + 6 : -6 * x + 6; }
double f2(double x) { return log(x + 1) / (x + 1); }
double f2p(double x) { return (1 - log(x + 1)) / ((x + 1) * (x + 1)); }
double f2pp(double x) {
return (2 * log(x + 1) - 3) / ((x + 1) * (x + 1) * (x + 1));
}
double f3(double x) { return log(x + 1) / (x + 1) + cos(10 * x); }
double f3p(double x) {
return (1 - log(x + 1)) / ((x + 1) * (x + 1)) - 10 * sin(10 * x);
}
double f3pp(double x) {
return (2 * log(x + 1) - 3) / ((x + 1) * (x + 1) * (x + 1)) - 100 * cos(10 * x);
}
vector<SplineSegment> cubic_spline(const vector<double>& x,
const vector<double>& y)
{
const int n = static_cast<int>(x.size()) - 1;
vector<double> h(n), alfa(n), l(n + 1), mu(n + 1), z(n + 1);
vector<double> a(y), b(n), c(n + 1), d(n);
textfor (int i = 0; i < n; ++i) h[i] = x[i + 1] - x[i]; for (int i = 1; i < n; ++i) alfa[i] = 3 / h[i] * (a[i + 1] - a[i]) - 3 / h[i - 1] * (a[i] - a[i - 1]); l[0] = 1; mu[0] = z[0] = 0; for (int i = 1; i < n; ++i) { l[i] = 2 * (x[i + 1] - x[i - 1]) - h[i - 1] * mu[i - 1]; mu[i] = h[i] / l[i]; z[i] = (alfa[i] - h[i - 1] * z[i - 1]) / l[i]; } l[n] = 1; z[n] = c[n] = 0; for (int j = n - 1; j >= 0; --j) { c[j] = z[j] - mu[j] * c[j + 1]; b[j] = (a[j + 1] - a[j]) / h[j] - h[j] * (c[j + 1] + 2 * c[j]) / 3; d[j] = (c[j + 1] - c[j]) / (3 * h[j]); } vector<SplineSegment> s(n); for (int i = 0; i < n; ++i) s[i] = { x[i],a[i],b[i],c[i],d[i] }; return s;
}
// ─────────── вывод в файл ───────────
void dump_coeffs(const string& fname,
const vector<double>& x,
const vector<SplineSegment>& s, const string& filename,double x_min,double x_max)
{
ofstream out(fname);
out << scientific << setprecision(15);
out << "i xi-1 xi aR bR cR dR\n";
textfor (int i = 1; i <= static_cast<int>(s.size()); ++i) { const auto& seg = s[i - 1]; const double h = x[i] - x[i - 1]; // преобразуем к правому узлу const double aR = seg.a + seg.b * h + seg.c * h * h + seg.d * h * h * h; const double bR = seg.b + 2 * seg.c * h + 3 * seg.d * h * h; const double cR = 2 * seg.c + 6 * seg.d * h; // вторая производная const double dR = 6 * seg.d; // третья производная out << i << ' ' << x[i - 1] << ' ' << x[i] << " " << aR << ' ' << bR << ' ' << cR << ' ' << dR << '\n'; }
}
// ─────────── проверка точности ───────────
void check(const string& tag,
const vector<SplineSegment>& spl,
double (*f)(double),
double (*fp)(double),
double (*fpp)(double),
double xmin, double xmax, int dense = 100)
{
const int m = spl.size() * dense;
double eF = 0, eFp = 0, eFpp = 0;
textfor (int k = 0; k <= m; ++k) { double x = xmin + (xmax - xmin) * k / m; int j = 0; while (j<int(spl.size()) - 1 && x>spl[j + 1].xi) ++j; double dx = x - spl[j].xi; const auto& seg = spl[j]; double S = seg.a + seg.b * dx + seg.c * dx * dx + seg.d * dx * dx * dx; double Sp = seg.b + 2 * seg.c * dx + 3 * seg.d * dx * dx; double Spp = 2 * seg.c + 6 * seg.d * dx; eF = max(eF, fabs(f(x) - S)); eFp = max(eFp, fabs(fp(x) - Sp)); eFpp = max(eFpp, fabs(fpp(x) - Spp)); } cout << tag << ": " << std::endl << "max|S-f|=" << scientific << eF << std::endl << "max|S'-f'|=" << eFp << std::endl << "max|S''-f''|=" << eFpp << '\n';
}
int main()
{
const int task_id = 1;
textif (task_id == 1) { const int N = 6; const double xmin = -1, xmax = 1; vector<double> x(N + 1), y(N + 1); for (int i = 0; i <= N; ++i) { x[i] = xmin + (xmax - xmin) * i / N; y[i] = f1(x[i]); } auto spl = cubic_spline(x, y); dump_coeffs("spline1_output.txt", x, spl,"funtcion1",-1,1); check("f1", spl, f1, f1p, f1pp, xmin, xmax); system("python test.py"); } else if (task_id == 2) { const int N = 5; const double xmin = 0.2, xmax = 2.0; vector<double> x(N + 1), y(N + 1); for (int i = 0; i <= N; ++i) { x[i] = xmin + (xmax - xmin) * i / N; y[i] = f2(x[i]); } auto spl = cubic_spline(x, y); dump_coeffs("spline2_output.txt", x, spl, "funtcion2",0.2,2); check("f2", spl, f2, f2p, f2pp, xmin, xmax); system("python main.py"); } else if (task_id == 3) { const int N = 11; const double xmin = 0.2, xmax = 2.0; vector<double> x(N + 1), y(N + 1); for (int i = 0; i <= N; ++i) { x[i] = xmin + (xmax - xmin) * i / N; y[i] = f3(x[i]); } auto spl = cubic_spline(x, y); dump_coeffs("spline3_output.txt", x, spl, "funtcion3",0.2,2); check("f3", spl, f3, f3p, f3pp, xmin, xmax); system("python main2.py"); } return 0;
}
Ниже — полностью обновлённый cpp-файл.
Я оставил весь прежний функционал (создание spline*_output.txt, вызовы check, system и т.д.), а также добавил:
j xj Fj Sj Fj-Sj F'j S'j F'j-S'j
;i x F''(x) S''(x) |F''-S''|
;#include <algorithm>
для std::max
.Файлы создаются в нужном формате для каждой задачи (1 → function1_.txt, 2 → function2_.txt, 3 → function3_*.txt).
cpp#include <iostream> #include <vector> #include <fstream> #include <cmath> #include <iomanip> #include <algorithm> // std::max using namespace std; struct SplineSegment { double xi; // левый узел сегмента [x_{i-1}, x_i] double a, b, c, d; // «левые» коэффициенты }; // ─────────── функции и их производные ─────────── double f1(double x) { return (x <= 0) ? x * x * x + 3 * x * x : -x * x * x + 3 * x * x; } double f1p(double x) { return (x <= 0) ? 3 * x * x + 6 * x : -3 * x * x + 6 * x; } double f1pp(double x) { return (x <= 0) ? 6 * x + 6 : -6 * x + 6; } double f2(double x) { return log(x + 1) / (x + 1); } double f2p(double x) { return (1 - log(x + 1)) / ((x + 1) * (x + 1)); } double f2pp(double x) { return (2 * log(x + 1) - 3) / ((x + 1) * (x + 1) * (x + 1)); } double f3(double x) { return log(x + 1) / (x + 1) + cos(10 * x); } double f3p(double x) { return (1 - log(x + 1)) / ((x + 1) * (x + 1)) - 10 * sin(10 * x); } double f3pp(double x) { return (2 * log(x + 1) - 3) / ((x + 1) * (x + 1) * (x + 1)) - 100 * cos(10 * x); } // ─────────── построение сплайна ─────────── vector<SplineSegment> cubic_spline(const vector<double>& x, const vector<double>& y) { const int n = static_cast<int>(x.size()) - 1; vector<double> h(n), alfa(n), l(n + 1), mu(n + 1), z(n + 1); vector<double> a(y), b(n), c(n + 1), d(n); for (int i = 0; i < n; ++i) h[i] = x[i + 1] - x[i]; for (int i = 1; i < n; ++i) alfa[i] = 3 / h[i] * (a[i + 1] - a[i]) - 3 / h[i - 1] * (a[i] - a[i - 1]); l[0] = 1; mu[0] = z[0] = 0; for (int i = 1; i < n; ++i) { l[i] = 2 * (x[i + 1] - x[i - 1]) - h[i - 1] * mu[i - 1]; mu[i] = h[i] / l[i]; z[i] = (alfa[i] - h[i - 1] * z[i - 1]) / l[i]; } l[n] = 1; z[n] = c[n] = 0; for (int j = n - 1; j >= 0; --j) { c[j] = z[j] - mu[j] * c[j + 1]; b[j] = (a[j + 1] - a[j]) / h[j] - h[j] * (c[j + 1] + 2 * c[j]) / 3; d[j] = (c[j + 1] - c[j]) / (3 * h[j]); } vector<SplineSegment> s(n); for (int i = 0; i < n; ++i) s[i] = { x[i], a[i], b[i], c[i], d[i] }; return s; } // ─────────── оценка сплайна и его производных ─────────── struct SplineEval { double S, Sp, Spp; }; SplineEval evaluate_spline(const vector<SplineSegment>& spl, const vector<double>& x_grid, double x) { int j = 0; const int nSeg = static_cast<int>(spl.size()); // для узловых точек берём левый сегмент, кроме самой первой if (x == x_grid.back()) j = nSeg - 1; else { while (j < nSeg - 1 && x > x_grid[j + 1]) ++j; } double dx = x - spl[j].xi; const auto& seg = spl[j]; double S = seg.a + seg.b * dx + seg.c * dx * dx + seg.d * dx * dx * dx; double Sp = seg.b + 2 * seg.c * dx + 3 * seg.d * dx * dx; double Spp = 2 * seg.c + 6 * seg.d * dx; return { S, Sp, Spp }; } // ─────────── вывод значений F-S и первых производных ─────────── void write_values(const string& fname, const vector<double>& x, const vector<SplineSegment>& spl, double (*f)(double), double (*fp)(double)) { ofstream out(fname); out << "j xj Fj Sj Fj-Sj F'j S'j F'j-S'j\n"; out << scientific << setprecision(15); for (size_t j = 0; j < x.size(); ++j) { SplineEval ev = evaluate_spline(spl, x, x[j]); double Fj = f(x[j]); double Fpj = fp(x[j]); out << j + 1 << ' ' << x[j] << ' ' << Fj << ' ' << ev.S << ' ' << Fj - ev.S << ' ' << Fpj << ' ' << ev.Sp << ' ' << Fpj - ev.Sp << '\n'; } } // ─────────── вывод вторых производных ─────────── void write_second_derivatives(const string& fname, const vector<double>& x, const vector<SplineSegment>& spl, double (*fpp)(double)) { ofstream out(fname); out << "i\tx\tF''(x)\tS''(x)\t|F''-S''|\n"; out << scientific << setprecision(15); for (size_t i = 0; i < x.size(); ++i) { SplineEval ev = evaluate_spline(spl, x, x[i]); double Fpp = fpp(x[i]); out << i + 1 << '\t' << x[i] << '\t' << Fpp << '\t' << ev.Spp << '\t' << fabs(Fpp - ev.Spp) << '\n'; } } // ─────────── вывод коэффициентов ─────────── void dump_coeffs(const string& fname, const vector<double>& x, const vector<SplineSegment>& s) { ofstream out(fname); out << scientific << setprecision(15); out << "i xi-1 xi aR bR cR dR\n"; for (int i = 1; i <= static_cast<int>(s.size()); ++i) { const auto& seg = s[i - 1]; const double h = x[i] - x[i - 1]; // преобразуем к правому узлу const double aR = seg.a + seg.b * h + seg.c * h * h + seg.d * h * h * h; const double bR = seg.b + 2 * seg.c * h + 3 * seg.d * h * h; const double cR = 2 * seg.c + 6 * seg.d * h; // вторая производная const double dR = 6 * seg.d; // третья производная out << i << ' ' << x[i - 1] << ' ' << x[i] << " " << aR << ' ' << bR << ' ' << cR << ' ' << dR << '\n'; } } // ─────────── проверка точности ─────────── void check(const string& tag, const vector<SplineSegment>& spl, double (*f)(double), double (*fp)(double), double (*fpp)(double), double xmin, double xmax, int dense = 100) { const int m = spl.size() * dense; double eF = 0, eFp = 0, eFpp = 0; for (int k = 0; k <= m; ++k) { double x = xmin + (xmax - xmin) * k / m; int j = 0; while (j < int(spl.size()) - 1 && x > spl[j + 1].xi) ++j; double dx = x - spl[j].xi; const auto& seg = spl[j]; double S = seg.a + seg.b * dx + seg.c * dx * dx + seg.d * dx * dx * dx; double Sp = seg.b + 2 * seg.c * dx + 3 * seg.d * dx * dx; double Spp = 2 * seg.c + 6 * seg.d * dx; eF = max(eF, fabs(f(x) - S)); eFp = max(eFp, fabs(fp(x) - Sp)); eFpp = max(eFpp, fabs(fpp(x) - Spp)); } cout << tag << ":\n" << "max|S-f| =" << scientific << eF << '\n' << "max|S'-f'| =" << eFp << '\n' << "max|S''-f''|=" << eFpp << '\n'; } int main() { const int task_id = 1; // 1, 2 или 3 if (task_id == 1) { const int N = 6; const double xmin = -1, xmax = 1; vector<double> x(N + 1), y(N + 1); for (int i = 0; i <= N; ++i) { x[i] = xmin + (xmax - xmin) * i / N; y[i] = f1(x[i]); } auto spl = cubic_spline(x, y); dump_coeffs("spline1_output.txt", x, spl); write_values("function1_values.txt", x, spl, f1, f1p); write_second_derivatives("function1_derivatives.txt", x, spl, f1pp); check("f1", spl, f1, f1p, f1pp, xmin, xmax); system("python test.py"); } else if (task_id == 2) { const int N = 5; const double xmin = 0.2, xmax = 2.0; vector<double> x(N + 1), y(N + 1); for (int i = 0; i <= N; ++i) { x[i] = xmin + (xmax - xmin) * i / N; y[i] = f2(x[i]); } auto spl = cubic_spline(x, y); dump_coeffs("spline2_output.txt", x, spl); write_values("function2_values.txt", x, spl, f2, f2p); write_second_derivatives("function2_derivatives.txt", x, spl, f2pp); check("f2", spl, f2, f2p, f2pp, xmin, xmax); system("python main.py"); } else if (task_id == 3) { const int N = 11; const double xmin = 0.2, xmax = 2.0; vector<double> x(N + 1), y(N + 1); for (int i = 0; i <= N; ++i) { x[i] = xmin + (xmax - xmin) * i / N; y[i] = f3(x[i]); } auto spl = cubic_spline(x, y); dump_coeffs("spline3_output.txt", x, spl); write_values("function3_values.txt", x, spl, f3, f3p); write_second_derivatives("function3_derivatives.txt", x, spl, f3pp); check("f3", spl, f3, f3p, f3pp, xmin, xmax); system("python main2.py"); } return 0; }
Теперь при запуске программы появляются дополнительные файлы function*_values.txt
и function*_derivatives.txt
с точно теми столбцами и порядком, который вы указали.