常用数值处理方法
递增填充 iota 函数
定义
定义在 numeric 头文件中的 iota() 函数模板会用连续的 T 类型值填充序列。前两个参数是定义序列的正向迭代器,第三个参数是初始的 T 值。 (T : 模板参数)
案例测试
#include <numeric>
……
#define Length 10
using namespace std;
int main()
{
int iarr[Length]{0};
vector<int> vec(iarr,iarr + Length);
itoa(vec.begin(),vec.end(),1);
for(int i=0;i<vec.size();i++)
{
cout << vec.at(i);
if(i < vec.size())
cout << " " ;
}
cout << endl;
}
结果截图
注意
iota 为定义在 C++ numeric中的库函数 , 作用是自动向容器填充递增数值。与其类似的另一个函数itoa 为 C 的 stdlib.h 库中的C字符串<->数字转换函数。功能、名称都不同,需要加以注意。
algorithm库中的fill函数也有填充的功能,不过默认无法有递增的效果。fill_if可添加相应谓词条件来实现功能。
容器求和函数 accumulate
定义
std : template <class InputIterator, class DateType, class BinaryPredicate>
accumulate为定义在numeric的函数,原生作用为容器区间累加求和,可实现数组求和。或者使用二元谓词"改造"此函数,实现我们想要的功能。DataType 为和的初始值。
测试
#include <numeric>
……
template <typename elem>
int FunHelper1(elem x ,elem y)
{
return x-y ;
}
using namespace std;
int main()
{
list<int> ls;
for (int i = 1; i <= 10; i++)
ls.push_back(i);
int sum = accumulate(ls.begin(), ls.end(), -55); //Sum(0~10) + (-55) = 55-55=0
printf("result1 = %d\n", sum);
int sums = accumulate(ls.begin(), ls.end(), -1, FunHelper1<int>);
//等同于-1 - {1+2+3+…+10} = -1 - 55 = -56
printf("result2 = %d\n", sums);
return 0;
}
结果截图
迭代序列和函数 partial_sum
定义
partial_sum函数计算容器的序列和,并将结果保存在另外一个容器。也可以定义二元谓词来重定义该方法的行为。
std : template <class InputIterator, class InputIterator, class OutputIterator ,class BinaryOperation>
测试
#include <numeric>
#include <functional>
……
using namespace std;
int main()
{
list<int> ls;
for (int i = 1; i <= 10; i++)
ls.push_back(i);
//输出到显示屏上
partial_sum(begin(ls), end(ls), ostream_iterator<int>{std::cout, " "});
cout << endl;
//使用了函数对象functional中的minus方法
partial_sum(begin(ls), end(ls), ostream_iterator<int>(cout, " "), minus<int>());
return 0;
}
结果截图
相邻差序列函数 adjacent_difference
定义
与上述方法相反,输出容器的每个元素为迭代求差。
测试
#include <numeric>
……
using namespace std;
int main()
{
vector<double> vec;
for (int i = 0; i <= 10; i++)
vec.push_back(i + i * 0.5);
cout << "默认求差" << endl;
adjacent_difference(begin(vec), end(vec), ostream_iterator<double>{cout, " "});
cout << endl;
cout << "重载序列差" << endl;
adjacent_difference(cbegin(vec), cend(vec), ostream_iterator<double>{std::cout, " "}, plus<double>());
cout << endl;
}
结果截图
向量内积函数 inner_product
定义
实现向量(矩阵)的数量积,本质为同维度向量1乘上另一个同维度向量2的转置形式。
std : template < class InputIterator , class InputIterator , class InputIterator , class DataType , class BinaryPredicate , class BinaryPredicate>
std : template < class InputIterator , class InputIterator , class DataType , BinaryPredicate>
前两个输入型迭代器为向量1的,第三个参数为向量2的输入迭代器,第四个参数为内积初值,后两个为二元谓词。
测试
#include <numeric>
#include <functional>
……
template<typename elem>
elem FunHelper2(elem x, elem y)
{
return 2 * x + 3 * y;
}
using namespace std;
int main()
{
vector<int> v1,v2;
for (int i = 0; i < 5; i++)
{
v1.push_back(i);
v2.push_back(-i);
}
int default_val = inner_product(v1.begin(), v1.end(), begin(v2), 0);
cout << "默认内积 = " << default_val << endl;
int new_val1 = inner_product(begin(v1), end(v1), begin(v2), 0, plus<int>(), minus<int>());
cout << "重载内积1 = " << new_val1 << endl;
int new_val2 = inner_product(begin(v1), end(v1), begin(v2), 0, FunHelper2<int>, multiplies<int>());
cout << "重载内积2 = " << new_val2 << endl;
return 0;
}
结果截图
数值数组 valarray
前提
c++ 中一共有3中’‘数组’’,基于基本类型实现的数组如int arr[100]、std 容器类如vector、array等、数值数组valarray,今天介绍的便是数值数组valarray。
定义
用于进行数组的数值运算,以获得最佳性能处理效果,而非灵活性;否则使用一般容器如array或者vector即可。
使用方法在构造上与vector极其相似,但其长度不可更改,这一点上与array类似。可以使用数组下标对容器进行随机访问。
常用方法
resize
使用resize重新调整容器大小,多留少删。
swap
交换两个同类数值数组的值。
shift/cshift
实现数值数组遍历的正向/反向移动(非二进制数的移位)。
apply
向使用数组所有元素施加一个特定的函数,并返回一个新的数值数组。
算数运算
四则运算
数值数组或纯数字之间的加减乘除,此时的乘法/除法运算等同于inner_product函数,加法/减法运算类似于partial_sum / adjacent_difference。
Sum
实现数值数组所有元素的和,效果优于accumulate函数
逻辑运算
当数值数组类型为bool时可进行类似于bitset的运算。
- 位与、位或、异或、位非等
- 移位、非
数学运算
使用位于cmath库中的数学运算,如三角函数、指数、对数运算等。
max/min
valarray的max/min方法可以返回其容器内的最大/最小值。
切片类slice
使用基于下标访问的辅助类来更好的访问数组。
构造方法
slice(start,sizes,stride)
- start 为起始位置
- sizes 为大小 , 对应提取出向量的长度
- stride为偏移量
测试
#include <numeric>
#include <valarray>
……
template <typename elemType>
void displayerDemo(elemType elem)
{
cout << elem << " ";
}
void main()
{
valarray<double> va11(10);
iota(begin(va11), end(va11), 0.5);
cout << "将va1视为5*2的矩阵" << endl;
cout << "va1 : " << endl;
for_each(begin(va11), end(va11), displayerDemo<double>);
cout << endl;
//行向量 v1
cout << "行向量:" << endl;
valarray<double> subva1 = va11[slice(1, 5, 2)];
for_each(begin(subva1), end(subva1), displayerDemo<double>);
cout << endl;
//列向量 v2
cout << "列向量:" << endl;
valarray<double> subva2 = va11[slice(2, 2, 5)];
for_each(begin(subva2), end(subva2), displayerDemo<double>);
cout << endl;
}
输出截图
测试