跳转到内容

C++ 数值操作

来自代码酷

C++数值操作[编辑 | 编辑源代码]

介绍[编辑 | 编辑源代码]

C++数值操作是C++标准模板库(STL)算法中专门用于处理数值计算的一组函数,定义在<<numeric>>头文件中。这些函数提供高效且类型安全的数值运算方式,包括累加、内积、部分和、相邻差等操作,适用于数组、向量等容器的数值处理。

数值操作算法是泛型编程的典型应用,通过迭代器抽象与容器解耦,支持自定义数值类型和运算规则。对于初学者,掌握这些函数能显著简化数值计算代码;对于高级用户,可通过自定义函数对象实现复杂数值逻辑。

核心算法[编辑 | 编辑源代码]

accumulate[编辑 | 编辑源代码]

计算区间内元素的累加和或自定义二元操作的累积结果。

语法:

template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );

template< class InputIt, class T, class BinaryOperation >
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );

示例:

#include <numeric>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v{1, 2, 3, 4, 5};
    
    // 基本累加
    int sum = std::accumulate(v.begin(), v.end(), 0);
    std::cout << "Sum: " << sum << "\n";  // 输出: Sum: 15
    
    // 自定义操作(乘积)
    int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
    std::cout << "Product: " << product;  // 输出: Product: 120
}

inner_product[编辑 | 编辑源代码]

计算两个区间的内积(点积)或自定义二元操作的类似计算。

语法:

template< class InputIt1, class InputIt2, class T >
T inner_product( InputIt1 first1, InputIt1 last1, InputIt2 first2, T init );

template< class InputIt1, class InputIt2, class T,
          class BinaryOperation1, class BinaryOperation2 >
T inner_product( InputIt1 first1, InputIt1 last1, InputIt2 first2, T init,
                 BinaryOperation1 op1, BinaryOperation2 op2 );

示例(向量点积):

std::vector<double> a{1.0, 2.0, 3.0};
std::vector<double> b{4.0, 5.0, 6.0};

double dot = std::inner_product(a.begin(), a.end(), b.begin(), 0.0);
// 1*4 + 2*5 + 3*6 = 32

partial_sum[编辑 | 编辑源代码]

计算区间元素的部分和序列或自定义二元操作的部分结果。

语法:

template< class InputIt, class OutputIt >
OutputIt partial_sum( InputIt first, InputIt last, OutputIt d_first );

template< class InputIt, class OutputIt, class BinaryOperation >
OutputIt partial_sum( InputIt first, InputIt last, OutputIt d_first,
                      BinaryOperation op );

示例:

std::vector<int> data{2, 3, 5, 7}, result(4);
std::partial_sum(data.begin(), data.end(), result.begin());
// result = {2, 5, 10, 17}

adjacent_difference[编辑 | 编辑源代码]

计算相邻元素的差值或自定义二元操作的结果。

语法:

template< class InputIt, class OutputIt >
OutputIt adjacent_difference( InputIt first, InputIt last, OutputIt d_first );

template< class InputIt, class OutputIt, class BinaryOperation >
OutputIt adjacent_difference( InputIt first, InputIt last, OutputIt d_first,
                             BinaryOperation op );

示例(计算差分):

std::vector<int> v{4, 6, 9, 13}, diff(4);
std::adjacent_difference(v.begin(), v.end(), diff.begin());
// diff = {4, 2, 3, 4} (第一个元素保持原值)

数学公式支持[编辑 | 编辑源代码]

部分数值算法对应数学概念:

  • 累加:accumulateS=i=firstlastxi
  • 内积:解析失败 (语法错误): {\displaystyle \text{inner\_product} \rightarrow P = \sum_{i} (a_i \times b_i)}

性能特征[编辑 | 编辑源代码]

flowchart LR A[算法] --> B[时间复杂度] B -->|accumulate| C[O(n)] B -->|inner_product| D[O(n)] B -->|partial_sum| E[O(n)] B -->|adjacent_difference| F[O(n)]

所有数值操作算法都具有线性时间复杂度,且不分配额外内存(输出迭代器除外)。

实际应用案例[编辑 | 编辑源代码]

案例1:金融计算 - 复利累积

std::vector<double> rates{0.01, 0.02, 0.015}; // 各期利率
double principal = 1000.0;
auto compound = [](double acc, double rate) { return acc * (1 + rate); };
double total = std::accumulate(rates.begin(), rates.end(), principal, compound);
// 计算: 1000*(1.01)*(1.02)*(1.015)

案例2:信号处理 - 移动平均

std::vector<int> signal{3, 5, 7, 2, 8}, ma_result(5);
std::partial_sum(signal.begin(), signal.end(), ma_result.begin());
// 转换为移动平均需后续处理:ma_result[i] /= (i+1)

高级用法[编辑 | 编辑源代码]

通过自定义函数对象实现复杂数值操作:

// 计算加权标准差
struct WeightedSum {
    double operator()(double acc, std::pair<double, double> p) const {
        return acc + p.first * p.second; // weight * value
    }
};
std::vector<std::pair<double, double>> weighted_data{{0.5, 10}, {1.5, 20}};
double weighted_total = std::accumulate(weighted_data.begin(), 
                                       weighted_data.end(), 
                                       0.0, 
                                       WeightedSum());

最佳实践[编辑 | 编辑源代码]

1. 对浮点数使用std::accumulate时,初始化值应显式指定类型(如0.0而非0) 2. 自定义操作函数应满足结合律(对于并行计算很重要) 3. 大数计算时考虑使用std::multiplies<void>等透明运算符避免类型转换

参见[编辑 | 编辑源代码]