《C++标准程序库》小结第十二章-数值

(一)复数

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

产生随机数

 

你可能感兴趣的:(《C++标准程序库》小结第十二章-数值)