Oracle Solaris Studio 12.2:C++ 用户指南

第 14 章 使用复数运算库

复数是由部和部组成的数。例如:

3.2 + 4i 1 + 3i 1 + 2.3i

在特例情况下,如 0 + 3i 是纯虚数,通常写为 3i5 + 0i 是纯实数,通常写为 5。可以使用 complex 数据类型来表示复数。


注 –

复数运算库 (libcomplex) 仅可用于兼容模式 ( -compat[ =4])。在标准模式(缺省模式)下,C++ 标准库 libCstd 附带具有类似功能的复数类。


14.1 复数库

复数运算库以新的数据类型实现复数数据类型,并提供:

复数也可表示为绝对值(或幅度)和参数(或角度)。该库提供了在实部虚部(笛卡尔)表示形式和幅度角度(极)表示形式之间进行转换的函数。

数字复共轭的虚部中有相反符号。

14.1.1 使用复数库

要使用复数库,应在程序中包含头文件 complex.h,并使用 -library=complex 选项进行编译和链接。

14.2 complex 类型

复数运算库定义了一个类:complex 类。complex 类的对象可以存放一个复数。复数由两部分构成:


class complex {
    double re, im;
};

complex 类的对象值是一对 double 值。第一个值表示实部,第二个值表示虚部

14.2.1 complex 类的构造函数

有两个用于 complex 的构造函数。它们的定义是:


complex::complex()            {re=0.0; im=0.0;}
complex::complex(double r, double i = 0.0) {re=r; im=i;}

如果声明复数变量时没有指定参数,则会使用第一个构造函数并初始化变量,因此两个部分都为 0。以下示例创建了一个其实部和虚部均为 0 的复数变量。


complex aComp;

您可以给定一个或两个参数。无论是以上哪种情况,都将使用第二个构造函数。如果只给定一个参数,该参数将作为实部的值,而虚部的值设置为 0。例如:


complex aComp(4.533);

用下列值创建一个复数变量:


4.533 + 0i

如果给定了两个值,第一个值被视为实部的值,而第二个值被视为虚部的值。例如:


complex aComp(8.999, 2.333);

用下列值创建一个复数变量:


8.999 + 2.333i

也可以使用复数运算库中提供的 polar 函数(请参见14.3 数学函数)创建复数。polar 函数根据给定的极坐标幅度和角度创建复数值。

没有用于 complex 类型的析构函数。

14.2.2 算术运算符

复数运算库定义了所有基本的算术运算符。具体来说,以下运算符按一般方法和普通的优先级工作:

+ - / * =

减法运算符 (-) 具有其通常的二元和一元含义。

此外,您可以按通常的方法使用以下运算符:

但是,若将以上四个运算符用于表达式,则不产生任何值。例如,下列表达式无法进行运算:


complex a, b;
...
if ((a+=2)==0) {...}; // illegal
b = a *= b; // illegal

另外还可以使用等号 (==) 和不等号 (!=),它们具有常规含义。

将运算表达式中的实数和复数混合时,C++ 使用复数运算符函数并将实数转换为复数。

14.3 数学函数

复数运算库提供了许多数学函数。一些是专用于复数的,而其余的则是标准 C 数学库中函数的复数版本。

全部这些函数为每个可能的参数产生结果。如果函数无法生成具有数学意义的结果,它就调用 complex_error 并返回适用的某值。具体来说,这些函数会尽量避免实际的溢出,而是调用 complex_error 并显示消息。下表描述了复数运算库函数的提示。


注 –

sqrtatan2 函数的实现遵循 C99 csqrt 附录 G 规范。


表 14–1 复数运算库函数

复数运算库函数  

说明 

double abs(const complex)

返回复数的幅度。 

double arg(const complex)

返回复数的角度。 

complex conj(const complex)

返回其参数的复共轭。 

double imag(const complex&)

返回复数的虚部。 

double norm(const complex)

返回其参数幅度的平方。比 abs 快,但较易产生溢出。用于比较幅度。

complex polar(double mag, double ang=0.0)

执行一对表示复数幅度和角度的极坐标,并返回对应的复数。 

double real(const complex&)

返回复数的实部。 

表 14–2 复数数学函数和三角函数

复数运算库函数

说明 

complex acos(const complex)

返回余弦为其参数的角度。 

complex asin(const complex)

返回正弦为其参数的角度。 

complex atan(const complex)

返回正切为其参数的角度。 

complex cos(const complex)

返回其参数的余切。 

complex cosh(const complex)

返回其参数的双曲余弦。 

complex exp(const complex)

计算 e**x,其中 e 为自然对数的基数,x 是为 exp 提供的参数。

complex log(const complex)

返回其参数的自然对数。 

complex log10(const complex)

返回其参数的常用对数。 

complex pow(double b, const complex exp)

complex pow(const complex b, int exp)

complex pow(const complex b, double exp)

complex pow(const complex b, const

complex exp)

使用两个参数:pow(b, exp ).它计算出 bexp 次幂。

complex sin(const complex)

返回其参数的正弦。 

complex sinh(const complex)

返回其参数的双曲正弦。 

complex sqrt(const complex)

返回其参数的平方根。 

complex tan(const complex)

返回其参数的正切。 

complex tanh(const complex)

返回其参数的双曲正切。 

14.4 错误处理

复数库具有以下用于错误处理的定义:


extern int errno;
class c_exception {...};
int complex_error(c_exception&);

外部变量 errno 是来自 C 库的全局错误状态。errno 可以为标准头文件 errno.h 中所列值(请参见 perror(3) 手册页)。没有任何函数会将 errno 设置为零,但有许多函数会将它设置为其他值。

要分辨特定运算是否失败:

  1. 在运算前将 errno 设置为零。

  2. 测试运算。

函数 complex_error 采用对类型 c_exception 的引用并由下列复数运算库函数调用:

缺省版本的 complex_error 返回零。这个零值的返回意味着发生了缺省的错误处理。可以提供自己的替换函数 complex_error,以执行其他错误处理。cplxerr(3CC4) 手册页中介绍了错误处理。

cplxtrig(3CC4) 和 cplxexp(3CC4) 手册页中介绍了缺省的错误处理,下表中也进行了简要介绍。

复数运算库函数  

缺省错误处理汇总  

exp

如果产生溢出,将 errno 设置为 ERANGE,并返回一个极大的复数。

log、log10

如果参数为零,将 errno 设置为 EDOM,并返回一个极大的复数。

sinh、cosh

如果参数的虚部产生溢出,则返回一个零复数。如果实部产生溢出,则返回一个极大的复数。无论是以上哪种情况,都将 errno 设置为 ERANGE

14.5 输入和输出

复数运算库提供了用于复数的缺省提取器插入器,如以下示例所示:


ostream& operator<<(ostream&, const complex&); //inserter
istream& operator>>(istream&, complex&); //extractor

有关提取器和插入器的基本信息,请参见13.2 iostream 交互的基本结构13.3.1 使用 iostream 进行输出

对于输入,复数提取器 >> 从输入流中提取一对数(用圆括号括住,并由逗号分隔开),并将其读入复数对象。第一个值被视为实部的值,而第二个值被视为虚部的值。例如,给定声明和输入语句:


complex x;
cin >> x;

以及输入 (3.45, 5),则 x 值等于 3.45 + 5.0i。对插入器来讲反向为真。如果给定 complex x(3.45, 5)cout<<x 将输出 (3.45, 5)

输入通常由括号中的一对数值(由逗号分隔)组成,也可选择空格。如果您提供一个单一数值(具有或不具有括号和空格),那么提取器会将数值的虚部设置为零。不要将符号 i 包括在输入文本中。

插入器会插入括号中实部和虚部的值(由逗号分隔)。它不包括符号 i。这两个值都视为 double

14.6 混合模式运算

类型 complex 专门用于处理混合模式表达式中的内置运算类型。运算类型会缺省转换为 complex 类型,而且算术运算符和大多数数学函数都有 complex 版本。例如:


int i, j;
double x, y;
complex a, b;
a = sin((b+i)/y) + x/j;

表达式 b+i 是混合模式。整数 i 通过构造函数 complex::complex(double,double=0) 转换为类型 complex(整型数先是转换为类型 double)。所得结果除以 double 类型的 y,因此 y 也转换为 complex 且使用了复数除法运算。这样,得到的商是 complex 类型,因此调用复数正弦例程,从而生成另一个 complex 结果等。

但是,并非所有的数学运算符和转换都是暗示的(即使定义)。例如从数学角度,复数未较好排序,只能比较等式。


complex a, b;
a == b; // OK
a != b; // OK
a <  b; // error: operator < cannot be applied to type complex
a >= b; // error: operator >= cannot be applied to type complex

同样,由于未明确定义概念,因此不会自动将类型 complex 转换为其他类型。您可以指定是否需要实部、虚部或幅度。


complex a;
double f(double);
f(abs(a)); // OK
f(a);      // error: no match for f(complex)

14.7 效率

设计 complex 类主要为了提高效率。

最简单的函数声明为 inline,以消除函数调用开销。

在函数不同时就会提供函数的多个开销版本。例如,pow 函数有多个版本,分别取类型为 doubleint 以及 complex 的指数,而前者的运算简单得多。

在包含 complex.h 时,会自动包含标准 C 数学库头文件 math.h。然后 C++ 开销规则就会产生类似于下面的表达式效率评估:


double x;
complex x = sqrt(x);

在此示例中,调用了标准数学函数 sqrt(double),且结果转换为 complex 类型,而不是先转换为 complex 类型再调用 sqrt(complex)。该结果转向重载决策规则的外部,正好是您所希望的结果。

14.8 复数手册页

复数运算库的剩余文档由下表所列的手册页组成:

表 14–3 有关 complex 类型的手册页

手册页 

概述  

cplx.intro(3CC4)

对复数运算库的一般性介绍 

cartpol(3CC4)

笛卡尔函数和极函数 

cplxerr(3CC4)

错误处理函数 

cplxexp(3CC4)

指数、对数和平方根函数 

cplxops(3CC4)

算术运算符函数 

cplxtrig(3CC4)

三角函数