用C++编写线性插值程序

我们定义LinearInterpolator类并在其中实现线性插值算法,并在在另一个类的成员函数中调用线性插值函数。由于线性插值数据数组可能会很大,确实需要考虑内存管理问题。在C++中,可以利用析构函数自动释放动态分配的内存。

下面是一个示例,假设我们在A1.hA1.cpp中实现对LinearInterpolator的调用。

LinearInterpolator.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pragma once

#include <vector>
#include <string>

class LinearInterpolator {
public:
LinearInterpolator(const std::string& filename);
double interpolate(double x) const;

private:
struct DataPoint {
double x;
double y;
};

std::vector<DataPoint> data;

void loadData(const std::string& filename);
};

LinearInterpolator.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "LinearInterpolator.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <stdexcept>

/// <summary>
/// 构造函数
/// </summary>
/// <param name="filename">数据文件路径</param>
LinearInterpolator::LinearInterpolator(const std::string& filename) {
loadData(filename);
}

/// <summary>
/// 读取数据
/// </summary>
/// <param name="filename">数据文件路径</param>
void LinearInterpolator::loadData(const std::string& filename) {
// 创建文件对象并打开文件
std::ifstream infile(filename);
if (!infile.is_open()) {
throw std::runtime_error("Could not open file.");
}

// 逐行读取数据
std::string line;
while (std::getline(infile, line)) {
// 跳过空行和注释行(以“#”开头的行)
if (line.empty() || line[0] == '#') continue;

// 将数据写到 data 向量中
std::istringstream iss(line);
DataPoint dp;
if (iss >> dp.x >> dp.y) {
data.push_back(dp);
}
}

infile.close();

// 保证X向量是按照从小到大的顺序排列的
std::sort(data.begin(), data.end(), [](const DataPoint& a, const DataPoint& b) {
return a.x < b.x;
});
}

/// <summary>
/// 线性插值
/// </summary>
/// <param name="x">X值</param>
/// <returns></returns>
double LinearInterpolator::interpolate(double x) const {
if (data.empty()) {
throw std::runtime_error("No data available for interpolation.");
}

// 处理超过上限或者下限的 X 值
if (x <= data.front().x) return data.front().y;
if (x >= data.back().x) return data.back().y;

// 找到正确的区间
auto it = std::lower_bound(data.begin(), data.end(), x, [](const DataPoint& dp, double value) {
return dp.x < value;
});

if (it == data.end()) return data.back().y;
if (it == data.begin()) return data.front().y;

auto it1 = it - 1;
auto it2 = it;

// 线性插值
double x1 = it1->x, y1 = it1->y;
double x2 = it2->x, y2 = it2->y;

return y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}

A1.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once

#include "LinearInterpolator.h"
#include <string>

class A1 {
public:
A1(const std::string& filename);
void someFunction(double x);

private:
LinearInterpolator interpolator; // 线性插值对象
};

#endif // A1_H

A1.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "A1.h"
#include <iostream>

A1::A1(const std::string& filename) : interpolator(filename) {
std::cout << "Construct A1 " << std::endl;
}

void A1::someFunction(double x) {
try {
double y = interpolator.interpolate(x);
std::cout << "Interpolated value at x = " << x << " is y = " << y << std::endl;
}
catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
}
}

int main() {
try {
// 假设数据文件路径为 data.txt
A1 a1("data.txt");

double x;
std::cout << "Enter a value for x: ";
std::cin >> x;

a1.someFunction(x);
}
catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
}

return 0;
}

代码说明

  1. LinearInterpolator
    • LinearInterpolator.hLinearInterpolator.cpp中定义和实现,包含数据加载和插值功能。
    • ~LinearInterpolator()析构函数用于在必要时释放资源(虽然std::vector会自动管理内存,但在这里为了示范,添加了析构函数)。
  2. A1
    • A1.hA1.cpp中定义和实现。
    • 包含LinearInterpolator的成员变量。
    • A1的构造函数中初始化插值器。
    • someFunction成员函数调用插值函数并输出结果。

通过这种方式,A1类整合了线性插值功能,并且可以在其成员函数中调用插值函数。在程序结束后,A1LinearInterpolator的析构函数将自动释放内存。由于使用了std::vector,其内存管理是自动的,不需要手动释放数据数组的空间。

with the help of ChatGPT


用C++编写线性插值程序
https://younotknowwho.github.io/2025/09/02/用C-编写线性插值程序/
Author
You Know Who
Posted on
September 2, 2025
Licensed under