У меня есть код на c++ который интерполирует 3 фун...

Создано: 28 мая 2025 г.

Отвечено с использованием O3 от Chat01

Вопрос

У меня есть код на 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);

text
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;

}

// ─────────── вывод в файл ───────────
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";

text
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;

text
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 << ": " << 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;

text
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,"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;

}

Мысль

Planning spline second derivatives

I'll start by computing the second derivatives of the spline at each index, using the full set of nodes. Since the second derivative of the spline is piecewise linear, it makes sense to do this evaluation at the node x values. The existing code only provides segment coefficients, so I need to expand it. I'll implement a function that can evaluate the spline and its derivatives at arbitrary points, especially at the nodes. We need to decide which segment to use when we reach the end of a segment.

Implementing second derivative outputs

To compute the second derivatives, I'll take the last segment if the point equals the segment's right endpoint. At the node xj, the second derivative is continuous, so I can compute it for the interior nodes. For each output, I'll include a formatted line with values like "i x F''(x) S''(x) |F''-S''|". I'll ensure the header matches exactly with what the user wants and use tab characters for spacing. I need to update the code with functions to evaluate and write values and derivatives to files.

Thought for 49 seconds

Ответ

Ниже — полностью обновлённый cpp-файл.
Я оставил весь прежний функционал (создание spline*_output.txt, вызовы check, system и т.д.), а также добавил:

  • evaluate_spline() — универсальную функцию, возвращающую S(x), S'(x) и S''(x);
  • write_values() — формирование function_values.txt с заголовком
    j xj Fj Sj Fj-Sj F'j S'j F'j-S'j;
  • write_second_derivatives() — формирование function_derivatives.txt с заголовком
    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; // &laquo;левые&raquo; коэффициенты }; // ─────────── функции и их производные ─────────── 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 с точно теми столбцами и порядком, который вы указали.

Поделиться этим Q&A