В С99 поддерживаются три комплексных типа:
• float /Complex
• double _Complex
• long double /Complex
Скажем, значение float Complex должно сохраняться с применением того же самого способа организации памяти, что и для двухэлементного массива float, где действительная часть сохраняется в первом элементе, а мнимая — во втором.
Реализации С99 и C11 могут поддерживать три мнимых типа:
• float _Imaginary
• double _Imaginary
• long double _Imaginary
Включение заголовочного файла complex.h позволяет использовать имя complex вместо /Complex и imaginary вместо _Imaginary.
Для комплексных типов определены арифметические операции, следующие обычным правилам математики. Например, значение (a + b* I) * ( c+d* I) равно:
(a*c-b*d)+(b*c+a*d)*1
910 Приложение Б
В заголовочном файле complex.h определено несколько макросов и функций, которые принимают и возвращают комплексные числа. В частности, макрос I представляет квадратный корень из -1. Это позволяет поступать следующим образом:
double complex cl = 4.2 + 2.0 * I; float imaginary c2= -3.0 * I;
Для присваивания значений комплексному числу в С11 предлагается второе средство — макрос CMPLX(). Например, если ге и int являются значениями double, можно сделать так:
double complex сЗ = CMPLX(re, im);
Смысл в том, что этот макрос может лучше обрабатывать необычные случаи, такие как ситуация, в которой im представляет собой бесконечность или не число, чем прямое присваивание.
В заголовочном файле complex.h содержится несколько прототипов комплексных функций. Многие из них являются комплексными эквивалентами функций math.h, в именах которых присутствует префикс с. Скажем, csin() возвращает комплексный синус своего комплексного аргумента. Другие функции касаются специфических свойств комплексных чисел. Например, creal() возвращает действительную часть комплексного числа, a cimag() — его мнимую часть в виде вещественного числа. То есть для переменной z типа double complex справедливо следующее:
z = creal (z) + cimag(z) * I;
Если вы знакомы с комплексными числами и нуждаетесь в их применении, вам стоит внимательно исследовать заголовочный файл complex.h.
Ниже показана короткая программа, иллюстрирующая часть поддержки комплексных чисел.
// complex.с — комплексные числа #include #include void show_cmlx(complex double cv); int main(void)
{
complex double vl = 4.0 + 3.0*1; double re, im; complex double v2; complex double sum, prod, conjug;
printf("Введите действительную часть комплексного числа: scanf("%lf", &re);
printf("Введите мнимую часть комплексного числа: scanf("%lf", &im);
// CMPLX() - это средство СИ
// v2 = CMPLX (re, im);
v2 = re + im * I;
printf("vl: ");
show_cmlx(vl);
putchar('\n');
printf("v2: ");
show_cmlx(v2);
putchar('\n');
sum = vl + v2;
prod = vl * v2;
conjug =conj (vl);
Справочные материалы 911
printf("сумма: "); show_cmlx(sum); putchar(‘\n'); printf("произведение: "); show_cmlx(prod); putchar('\n');
printf("комплексное сопряжение vl: "); show_cmlx(conjug); putchar('\n');
return 0;
)
void show_cmlx(complex double cv)
{
printf("(%.2f, %.2fi)", creal(cv), cimag(cv)); return;
}
Если вы используете C++, то вам следует иметь в виду, что заголовочный файл C++ по имени complex предлагает способ работы с комплексными числами, основанный на классах, который существенно отличается от средств complex.h языка С.
Раздел IX. Отличия между С и C++
Большей частью язык C++ представляет собой надмножество С — в том смысле, что допустимая программа на С также является допустимой программой на C++. Главные отличия между C++ и С связаны со многими дополнительными средствами, которые поддерживает язык C++. Тем не менее, существует ряд областей, где правила C++ несколько отличаются от их эквивалентов в С. Эти отличия могут стать причиной того, что программа на С будет работать слегка иначе или даже вовсе не работать, если вы скомпилируете ее как программу C++. Именно эти отличия рассматриваются в данном разделе приложения. Если вы компилируете свои программы на С компилятором, который поддерживает только C++, но не С, вам необходимо знать о таких отличиях. Хотя они весьма незначительно влияют на примеры, приведенные в книге, иногда отличия могут приводить к тому, что некоторые экземпляры допустимого кода С вызывают появление сообщений об ошибках, если код компилируется как программа C++.
Выпуск стандарта С99 усложняет ситуацию, поскольку в некоторых местах он делает С ближе к C++. Например, он позволяет разносить объявления по телу кода и распознает вариант комментария //.В других отношениях С99 углубляет отличия от C++, например, за счет добавления массивов переменной длины и ключевого слова restrict. Стандарт C11 кое в чем уменьшил брешь, к примеру, введя тип charl6_t, добавив ключевое слово _Alignas и создав макрос alignas для соответствия ключевому слову C++. Учитывая раннюю стадию развития С11 и неполное принятие С99 некоторыми поставщиками, мы сталкиваемся с отличиями между С90, С99 и СП, а также с отличиями между С++11 и каждым из упомянутых стандартов С. В этом разделе мы обратимся к будущему и обсудим ряд отличий между С99, C11 и C++. Тем временем, язык C++ также развивается, так что точные соответствия и несовпадения между языками С и C++ продолжат изменяться.
Читать дальше