3.2 + 4i 1 + 3i 1 + 2.3i
在特例情况下,如 0 + 3i 是纯虚数,通常写为 3i;5 + 0i 是纯实数,通常写为 5。可以使用 complex 数据类型来表示复数。
复数运算库 (libcomplex) 仅可用于兼容模式 ( -compat[ =4]) 下。在标准模式(缺省模式)下,C++ 标准库 libCstd 中附带具有类似功能的复数类。
运算符
数学库函数(为内建数字类型定义)
扩展(用于允许复数输入和输出的 iostream)
错误处理机制
复数也表示为绝对值(或幅度)和参数(或角度)。该库提供了在实部虚部(笛卡尔)表示形式和幅度角度(极)表示形式之间进行转换的函数。
数字复共轭的虚部中有相反符号。
要使用复数库,应在程序中包含头文件 complex.h,并使用 -library=complex 选项进行编译和链接。
复数运算库定义了一个类:complex 类。complex 类的对象可以存放一个复数。复数由两部分构成:
实部
虚部
class complex { double re, im; }; |
complex 类的对象值是一对 double 值。第一个值表示实部,第二个值表示虚部。
有两个用于 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 函数(请参见15.3 数学函数)创建复数。polar 函数根据给定的极坐标幅度和角度创建复数值。
没有用于 complex 类型的析构函数。
复数运算库定义了所有基本的算术运算符。具体来说,以下运算符按一般方法和普通的优先级工作:
+ - / * =
减法运算符 (-) 具有其通常的二元和一元含义。
此外,您可以按通常的方法使用以下运算符:
加法赋值运算符 (+=)
减法赋值运算符 (-=)
乘法赋值运算符 (*=)
除法赋值运算符 (/=)
但是,若将以上四个运算符用于表达式,则不产生任何值。例如,下列表达式无法进行运算:
complex a, b; ... if ((a+=2)==0) {...}; // illegal b = a *= b; // illegal |
另外还可以使用等号 (==) 和不等号 (!=),它们具有常规含义。
将运算表达式中的实数和复数混合时,C++ 使用复数运算符函数并将实数转换为复数。
复数运算库提供了许多数学函数。一些是专用于复数的,而其余的则是标准 C 数学库中函数的复数版本。
全部这些函数为每个可能的参数产生结果。如果函数无法生成具有数学意义的结果,它就调用 complex_error 并返回适用的某值。具体来说,这些函数会尽量避免实际的溢出,而是调用 complex_error 并显示消息。下表描述了复数运算库函数的提示。
sqrt 和 atan2 函数的实现遵循 C99 csqrt 附录 G 规范。
复数运算库函数 |
说明 |
---|---|
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&) |
返回复数的实部。 |
表 15–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 ). 它计算出 b 的 exp 次幂。 |
complex sin(const complex) |
返回其参数的正弦。 |
complex sinh(const complex) |
返回其参数的双曲正弦。 |
complex sqrt(const complex) |
返回其参数的平方根。 |
complex tan(const complex) |
返回其参数的正切。 |
complex tanh(const complex) |
返回其参数的双曲正切。 |
extern int errno; class c_exception {...}; int complex_error(c_exception&); |
外部变量 errno 是来自 C 库的全局错误状态。errno 可以为标准头文件 errno.h 中所列值(请参见 perror(3) 手册页)。没有任何函数会将 errno 设置为零,但有许多函数会将它设置为其他值。
要分辨特定运算是否失败:
在运算前将 errno 设置为零。
测试运算。
函数 complex_error 采用对类型 c_exception 的引用并由下列复数运算库函数调用:
exp
log
log10
sinh
cosh
缺省版本的 complex_error 返回零。这个零值的返回意味着发生了缺省的错误处理。可以提供自己的替换函数 complex_error,以执行其他错误处理。cplxerr(3CC4) 手册页中介绍了错误处理。
cplxtrig(3CC4) 和 cplxexp(3CC4) 手册页中介绍了缺省的错误处理,下表中也进行了简要介绍。
复数运算库函数 |
缺省错误处理汇总 |
---|---|
exp | |
log、log10 | |
sinh、cosh |
如果参数的虚部产生溢出,则返回一个零复数。如果实部产生溢出,则返回一个极大的复数。无论是以上哪种情况,都将 errno 设置为 ERANGE。 |
复数运算库提供了用于复数的缺省提取器和插入器,如以下示例所示:
ostream& operator<<(ostream&, const complex&); //inserter istream& operator>>(istream&, complex&); //extractor |
有关提取器和插入器的基本信息,请参见14.2 iostream 交互的基本结构和14.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。
类型 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) |
设计 complex 类主要为了提高效率。
最简单的函数声明为 inline,以消除函数调用开销。
在函数不同时就会提供函数的多个开销版本。例如,pow 函数有多个版本,分别取类型为 double 和 int 以及 complex 的指数,而前者的运算简单得多。
在包含 complex.h 时,会自动包含标准 C 数学库头文件 math.h。然后 C++ 开销规则就会产生类似于下面的表达式效率评估:
double x; complex x = sqrt(x); |
在此示例中,调用了标准数学函数 sqrt(double),且结果转换为类型 complex,而不是先转换为类型 complex 再调用 sqrt(complex)。该结果转向重载决策规则的外部,正好是您所希望的结果。
复数运算库的剩余文档由下表所列的手册页组成:
表 15–3 有关 complex 类型的手册页
手册页 |
概述 |
---|---|
cplx.intro(3CC4) |
对复数运算库的一般性介绍 |
cartpol(3CC4) |
笛卡尔函数和极函数 |
cplxerr(3CC4) |
错误处理函数 |
cplxexp(3CC4) |
指数、对数和平方根函数 |
cplxops(3CC4) |
算术运算符函数 |
cplxtrig(3CC4) |
三角函数 |