Шрифт:
Интервал:
Закладка:
return v;
}
И вновь простая операция над объектом класса Matrix делает за нас большую часть работы. Как указывалось в разделе 24.5.3, операции вывода объектов класса Matrix описаны в заголовке MatrixIO.h. Функции random_matrix() и random_vector() просто используют случайные числа (раздел 24.7). Читатели могут написать эти функции в качестве упражнения. Имя Index является синонимом типа индекса, используемого в библиотеке Matrix, и определено с помощью оператора typedef (раздел A.15). Этот тип включается в программу с помощью объявления using.
using Numeric_lib::Index;
24.7. Случайные числа


int rand(); // возвращает числа из диапазона
// [0:RAND_MAX]
RAND_MAX // наибольшее число, которое генерирует
// датчик rand()
void srand(unsigned int); // начальное значение датчика
// случайных чисел
Повторяющиеся вызовы функции rand() генерируют последовательность чисел типа int, равномерно распределенных в диапазоне [0:RAND_MAX]. Эта последовательность чисел называется псевдослучайной, потому что она генерируется с помощью математической формулы и с определенного места начинает повторяться (т.е. становится предсказуемой и не случайной). В частности, если мы много раз вызовем функцию rand() в программе, то при каждом запуске программы получим одинаковые последовательности. Это чрезвычайно полезно для отладки. Если же мы хотим получать разные последовательности, то должны вызывать функцию srand() с разными значениями. При каждом новом аргументе функции srand() функция rand() будет порождать разные последовательности.
Например, рассмотрим функцию random_vector(), упомянутую в разделе 24.6.3. Вызов функции random_vector(n) порождает объект класса Matrix<double,1>, содержащий n элементов, представляющих собой случайные числа в диапазоне от [0:n]:
Vector random_vector(Index n)
{
Vector v(n);
for (Index i = 0; i < n; ++i)
v(i) = 1.0 * n * rand() / RAND_MAX;
return v;
}
Обратите внимание на использование числа 1.0, гарантирующего, что все вычисления будут выполнены в арифметике с плавающей точкой. Иначе при каждом делении целого числа на RAND_MAX мы получали бы 0.
Сложнее получить целое число из заданного диапазона, например [0:max]. Большинство людей сразу предлагают следующее решение:
int val = rand()%max;
Долгое время такой код считался совершенно неудовлетворительным, поскольку он просто отбрасывает младшие разряды случайного числа, а они, как правило, не обладают свойствами, которыми должны обладать числа, генерируемые традиционными датчиками случайных чисел. Однако в настоящее время во многих операционных системах эта проблема решена достаточно успешно, но для обеспечения переносимости своих программ мы рекомендуем все же скрывать вычисления случайных чисел в функциях.
int randint(int max) { return rand()%max; }
int randint(int min, int max) { return randint(max–min)+min; }

24.8. Стандартные математические функции
В стандартной библиотеке есть стандартные математические функции (cos, sin, log и т.д.). Их объявления можно найти в заголовке <cmath>.

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

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 и чему он может быть равен, обратитесь к документации.
