Чтение онлайн

ЖАНРЫ

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

int randint(int min, int max) { return randint(max–min)+min; }

Таким образом, мы можем скрыть определение функции
randint
, если окажется, что реализация функции
rand
является неудовлетворительной. В промышленных программных системах, а также в приложениях, где требуются неравномерные распределения, обычно используются качественные и широко доступные библиотеки случайных чисел, например
Boost::random
. Для того чтобы получить представление о качестве вашего датчика случайных чисел, выполните упр. 10.

24.8.

Стандартные математические функции

В стандартной библиотеке есть стандартные математические функции (

cos
,
sin
,
log
и т.д.). Их объявления можно найти в заголовке
<cmath>
.

Стандартные математические функции могут иметь аргументы типов

float
,
double
,
long double
и
complex
(раздел 24.9). Эти функции очень полезны при вычислениях с плавающей точкой. Более подробная информация содержится в широко доступной документации, а для начала можно обратиться к документации, размещенной в веб.

Если стандартная математическая функция не может дать корректного результата, она устанавливает флажок
errno
. Рассмотрим пример.

errno = 0;

double s2 = sqrt(–1);

if (errno) cerr << "Что-то где-то пошло не так, как надо";

if (errno == EDOM) // ошибка из-за выхода аргумента

// за пределы области определения

cerr << " фунция sqrt для отрицательных аргументов
не определена.";

pow(very_large,2); // плохая идея

if (errno==ERANGE) // ошибка из-за выхода за пределы допустимого

// диапазона

cerr << "pow(" << very_large

<< ",2) слишком большое число для double";

Если вы выполняете серьезные математические вычисления, то всегда должны проверять значение

errno
, чтобы убедиться, что после возвращения результата оно по-прежнему равно
0
. Если нет, то что-то пошло не так, как надо. Для того чтобы узнать, какие математические функции могут устанавливать флажок
errno
и чему он может быть равен, обратитесь к документации.

Как показано в примере, ненулевое значение флажка
errno
просто означает, что что-то пошло не так. Функции, не входящие в стандартную библиотеку, довольно часто также устанавливают флажок
errno
при выявлении ошибок, поэтому следует точнее анализировать разные значения переменной
errno
, чтобы понять, что именно случилось. В данном примере до вызова стандартной библиотечной функции переменная
errno
была равна нулю, а проверка значения
errno
сразу после выполнения функции может обнаружить, например, константы
EDOM
и
ERANGE
. Константа
EDOM
означает ошибку, возникшую из-за выхода аргумента за пределы области определения функции (domain error). Константа
ERANGE
означает выход за пределы допустимого диапазона значений (range error).

Обработка ошибок с помощью

переменной
errno
носит довольно примитивный характер. Она уходит корнями в первую версию (выпуска 1975 года) математических функций языка C.

24.9. Комплексные числа

Комплексные числа широко используются в научных и инженерных вычислениях. Мы полагаем, что раз они вам необходимы, значит, вам известны их математические свойства, поэтому просто покажем, как комплексные числа выражаются в стандартной библиотеке языка С++. Объявление комплексных чисел и связанных с ними математических функций находятся в заголовке

<complex>
.

template<class Scalar> class complex {

// комплексное число — это пара скалярных величин,

// по существу, пара координат

Scalar re, im;

public:

complex(const Scalar & r, const Scalar & i) :re(r), im(i) { }

complex(const Scalar & r) :re(r),im(Scalar ) { }

complex :re(Scalar ), im(Scalar ) { }

Scalar real { return re; } // действительная часть

Scalar imag { return im; } // мнимая часть

// операторы : = += –= *= /=

};

Стандартная библиотека

complex
поддерживает типы скалярных величин
float
,
double
и
long double
. Кроме членов класса
complex
и стандартных математических функций (раздел 24.8), заголовок
<complex>
содержит множество полезных операций.

Примечание: в классе

complex
нет операций
<
и
%
.

Класс

complex<T>
используется так же, как любой другой встроенный тип, например
double
. Рассмотрим пример.

typedef complex<double> dcmplx; // иногда выражение complex<double>

// является слишком громоздким

void f(dcmplx z, vector<dcmplx>& vc)

{

dcmplx z2 = pow(z,2);

dcmplx z3 = z2*9.3+vc[3];

dcmplx sum = accumulate(vc.begin, vc.end, dcmplx);

// ...

}

Помните, что не все операции над числами типов

int
и
double
определены для класса
complex
. Рассмотрим пример.

if (z2<z3) // ошибка: операция < для комплексных чисел не определена

Обратите внимание на то, что представление (схема) комплексных чисел в стандартной библиотеке языка С++ сопоставима с соответствующими типами в языках C и Fortran.

24.10. Ссылки

По существу, вопросы, поднятые в этой главе, такие как ошибки округления, операции над матрицами и арифметика комплексных чисел, сами по себе интереса не представляют. Мы просто описываем некоторые возможности, предоставляемые языком С++, людям, которым необходимо выполнять математические вычисления.

Поделиться с друзьями: