79-对复数的支持
B.8.5 对复数的支持
复数是有实部和虚部的数。实部是普通的实数,如浮点类型表示的数。虚部表示一个虚数。虚数是 -1 的平方根的倍数。在数学中,复数通常写作类似 4.2 + 2.0i 的形式,其中 i 表示 -1 的平方根。
C99支持3种复数类型(在C11中为可选):
float _Complexdouble _Complexlong double _Compplex
例如,存储 float _Complex 类型的值时,使用与两个 float 类型元素的数组相同的内存布局,实部值存储在第 1 个元素中,虚部值存储在第 2 个元素中。
C99和C11还支持下面3种虚类型:
float _Imaginarydouble _Imaginarylong double _Imaginary
包含了 complex.h 头文件,就可以用 complex 代替 _Complex ,用 imaginary 代替 _Imaginary 。
为复数类型定义的算术运算遵循一般的数学规则。例如, (a+b I) (c+d I) 即是 (a c-b d)+(b c+a d) I 。
complex.h 头文件定义了一些宏和接受复数参数并返回复数的函数。特别是,宏 I 表示 -1 的平方根。因此,可以编写这样的代码:
double complex c1 = 4.2 + 2.0 * I;
float imaginary c2= -3.0 * I;
C11提供了另一种方法,通过 CMPLX() 宏给复数赋值。例如,如果 re 和 im 都是 double 类型的值,可以这样做:
double complex c3 = CMPLX(re, im);
这种方法的目的是,宏在处理不常见的情况(如, im 是无穷大或非数)时比直接赋值好。
complex.h 头文件提供了一些复数函数的原型,其中许多复数函数都有对应 math.h 中的函数,其函数名即是对应函数名前加上 c 前缀。例如, csin() 返回其复数参数的复正弦。其他函数与特定的复数特性相关。例如, creal() 函数返回一个复数的实部, cimag() 函数返回一个复数的虚部。也就是说,给定一个 double conplex 类型的 z ,下面的代码为真:
z = creal(z) + cimag(z) * I;
如果熟悉复数,需要使用复数,请详细阅读 complex.h 中的内容。
下面的示例演示了对复数的一些支持:
// complex.c -- 复数
#include <stdio.h>
#include <complex.h>
void show_cmlx(complex double cv);
int main(void)
{
complex double v1 = 4.0 + 3.0*I;
double re, im;
complex double v2;
complex double sum, prod, conjug;
printf("Enter the real part of a complex number: ");
scanf("%lf", &re);
printf("Enter the imaginary part of a complex number: ");
scanf("%lf", &im);
// CMPLX()是C11中的一个特性
// v2 = CMPLX(re, im);
v2 = re + im * I;
printf("v1: ");
show_cmlx(v1);
putchar('\n');
printf("v2: ");
show_cmlx(v2);
putchar('\n');
sum = v1 + v2;
prod = v1 * v2;
conjug =conj(v1);
printf("sum: ");
show_cmlx(sum);
putchar('\n');
printf("product: ");
show_cmlx(prod);
putchar('\n');
printf("complex congjugate of v1: ");
show_cmlx(conjug);
putchar('\n');
return 0;
}
void show_cmlx(complex double cv)
{
printf("(%.2f, %.2fi)", creal(cv), cimag(cv));
return;
}
如果使用C++,会发现C++的 complex 头文件提供一种基于类的方式处理复数,这与C的 complex.h 头文件使用的方法不同。