(一)复数
1、复数相关算法少,请移步科学计算库。
2、C++中使用复数complex需要#include <complex>。复数普通表现形式为a+bi,也可以通过polar函数转化:
complex<double>c1(4.0,3.0);
complex<double>c2(polar(5.0,0.75));//极坐标转化,模和幅角
注意,complex<高精度>可以隐式转化到低精度,但反之没有,必须显示。
3、complex输入时,需要打上括号和逗号。
4、complex可以与实数、复数判断相等,但不能比较大小。
5、函数:
函数名 |
作用 |
polar |
产生一个complex<double>。由于没有从complex<double>到complex<其他低精度类型>的隐式转化,故一般用在构造函数。 |
conj |
产生一个共轭的复数 |
real |
实部 |
imag |
虚部 |
norm |
绝对值的平方 |
arg |
极坐标的相位角 |
pow,sqrt,log,sin,cos,tan,sinh, cosh,tanh |
|
log10 |
10为底的对数 |
exp |
e为底的幂 |
(二)valarray
1、valarray代表数值线性序列,#include <valarray>。作者认为设计较差,非高性能数学计算场合可以使用,高性能场合请用其他专用科学计算库。
2、valarray与STL兼容性不好,很多算法无法使用。
3、三角函数和指数运算直接使用C++提供的数值函数就行,比如sqrt,sin。
4、valarray的亮点就是类似于python的子集分割。这项操作依赖于缓式评估技术,以达到高性能。所获得的子集只是定义,在最终需要结果的时候(operator=函数)才转化为实际的valarray。不能直接使用slice,subset。
a) slice切割
b) general slice一般化切割
c) masked subset屏蔽式子集
d) indirect subset 间接式子集
5、valarray的子集设计并不好,下面代码是错的:
va[slice(0,4,3)] = va[slice(1,4,3)] * va[slice(2,4,3)];//错误!!
原因是没有实作出,定义式的operator*函数,因此操作必须加上显示转化符号,将子集转化为实际的valarray后调用valarray的operator*函数。
va[slice(0,4,3)] = valarray<double>(va[slice(1,4,3)])* valarray<double>(va[slice(2,4,3)]);
为了方便起见,我们可以定义一个模板函数自动转化valarray”:
template <class T>
inline std::valarray<typename T::value_type> VA(constT& valarray_subset)
{
return std::valarray<typenameT::value_type> (valarray_subset);
}
这里编译器会进行RVO(返回值优化)操作,性能比临时的好。现在代码如下:
va[slice(0,4,3)] = VA(va[slice(1,4,3)]) * VA(va[slice(2,4,3)]);
6、切割具备三个属性:
a) 起始索引
b) 元素数量size
c) 元素间距stride
7、一般化切割,属性:
a) 起始索引
b) 元素数量size
c) 元素间距stride
与切割不同,元素数量和元素间距可以是一个数组。代码:
size_tlenvalue[] = {2,4};
size_tstridevalue[] = {10,3};
valarray<size_t>len(lenvalue, 2);
valarray<size_t>stride(stridevalue, 2);
va[gslice(2,len. stride)];
表示从索引2开始,以10为间隔提取了2次,以3为间隔提取4次:
2,5,8,11
12,15,18,21.
这个真不好用,不深究它。
8、屏蔽式子集很简单:
va[va>7.0&& va < 9.0];
9、间接式子集
valarray<size_t>idx;
给idx赋值。
va[idx];
简单说就是把valarray作为子集索引了。
10、函数
函数名 |
作用 |
min |
最小 |
max |
最大 |
shift(num) |
被移空的元素赋初值。num为正数,向左移动 |
cshift(num) |
循环移动,num为正数向左移动。 |
可以使用各种逻辑符号:==,!=,<, > , &&, || |
|
<<=, >>= |
后面可以跟valarray,对每个元素进行二进制位移 |
apply(op) |
类似于Eigen和VXL的东西,对每个元素调用op函数 |
超越函数: abs, pow, exp, sqrt, log, log10, sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, atan2 |
|
(三)全局性数值函数,C语言也能用
函数 |
作用 |
pow |
求幂 |
exp |
指数 |
sqrt |
平方根 |
log |
自然对数 |
log10 |
10为底的对数 |
sin |
正弦 |
cos |
余弦 |
tan |
正切 |
sinh |
双曲正弦 |
cosh |
双曲余弦 |
tanh |
双曲正切 |
asin |
反正弦 |
acos |
反余弦 |
atan |
反正切 |
atan2 |
给定平面坐标的XY。商的反正切,可以返回360度角度的值,逆时针方向,从而得知目标在哪个象限。返回区间(-pi,pi] |
ceil |
大于浮点数的最小整数 |
floor |
小于浮点数的最大整数 |
fabs |
浮点数绝对值。也可用C++的abs完全代替。 |
fmod |
浮点数取余 |
frexp |
double frexp( double x, int *expptr ); expptr是2为底的幂数。例子:frexp( 16.400000, &n ) = 0.512500, n = 5。验证: 16.4 = 0.5125 * 2^5 = 0.5125 * 32 |
ldexp |
double ldexp(double value, int exp);将浮点数乘以2的某个整数幂次方。例子:x = ldexp(4.0,3); x = 4 * 2^3 = 4 * 8 = 32. |
modf |
double modf(double x, double *intptr); double fraction, integer; fraction = modf(100000.567, &integer); fraction = 0.567; integer = 100000。 |
div |
求int相除的商和余数。div_t x;x = div(10,3); x.quot = 3; x.rem =1; |
srand |
随机数种子 |
rand |
产生随机数 |