Работа с числами
4.5.2. Уплотнённые массивы
Одним из преимуществ языка программирования Mathematica является гибкость в отношении обработки данных различных типов. Например, когда пользователь выполняет расчёты с числами с плавающей запятой, Mathematica определяет тип чисел, с которыми ведётся работа, а затем определяет, следует ли пользоваться стандартным алгоритмом вычислений с машинной точностью или нужно пользоваться иным алгоритмом для осуществления вычислений с повышенной точностью. Такая самостоятельность Mathematica значительно упрощает работу пользователя, однако, за это приходится платить. Платой является необходимость хранения и использования служебной информации. В случае небольших расчётов объём служебной информации незначителен и может не приниматься во внимание, однако при работе с большими массивами данных, например, включающими десятки тысяч строк и столбцов, объём служебной информации значительно возрастает и может серьёзно тормозить вычисления. К счастью, в Mathematica имеется возможность обойтись без части служебной информации, получить ощутимый прирост скорости и уменьшить занимаемый объём памяти. Достигается это при помощи уплотнённых массивов: уплотнённый массив Mathematica представляет список однотипных (целые, вещественные, комплексные) чисел. Для иллюстрации эффекта использования уплотнённых массивов вновь воспользуемся примерами из работы П. Веллина и др. [14, с. 250–251].
В примере In[1] на рис. 4.17 зададим список случайных вещественных чисел размерностью 1000x1000. Поскольку все числа в списке одного типа (вещественные), то Mathematica автоматически рассматривает этот список как уплотнённый массив. Убедиться, является ли список list уплотнённым массивом, мы можем при помощи функции Developer`PackedArrayQ[list]. В случае если является, функция возвращает True (пример In[2]).
На основе уже имеющегося уплотнённого массива создадим неуплотнённый массив, для чего заменим один из элементов имеющегося массива числом, отличным от вещественного, например, заменим целым числом 10 число в 5 строке, 5 столбце — пример In[3] на рис. 4.17; в In[4] мы убеждаемся в том, что полученный массив не является уплотнённым (функция Developer`PackedArrayQ[list] возвращает False).
Теперь проверим при помощи уже известной нам функции ByteCount объём памяти, который занимает каждый из заданных нами массивов — пример In[5]. Первый массив, который является уплотнённым, занимает объём памяти примерно в два с половиной раза меньше, чем второй, не являющийся уплотнённым (Out[5]).
В примере In[6] на рис. 4.17 мы найдём время, затрачиваемое на нахождение максимального значения в каждом из массивов. На первый массив Mathematica затрачивает меньше миллионной доли секунды, поскольку указывает на выходе 0., во втором же на вычисления затрачивается больше сотой доли секунды.
Таким образом, работа с уплотнёнными массивами оказывается более выгодной и в плане объёма памяти, и в плане скорости вычислений.
Большинство встроенных функций организованы таким образом, что они гораздо эффективней работают с уплотнёнными массивами. Однако если время, затрачиваемое программой на обработку обычного списка, близко ко времени обработки уплотнённого массива, то функция не вынуждает Mathematica создавать уплотнённый массив, а продолжает работать с обычным списком.
Для каждой встроенной функции существует собственный минимальный размер списка, при котором он конвертируется в уплотнённый массив. Например, для функции Table это значение равно 250. Если список, заданный этой функцией, содержит число элементов, меньшее, чем 250, то он обрабатывается как обычный список, в противном случае — как уплотнённый массив (ср. примеры In[7] и In[8] на рис. 4.17). Функция Range генерирует уплотнённые массивы при любых аргументах больше 1 (пример In[9]).
Подробней о работе с уплотнёнными массивами см. книгу П. Веллина и др. [14, с. 250–253].
4.6. Округление чисел
Сколь бы ни было прекрасно работать только с точными и приближенными с высокой точностью числами, зачастую просто нет необходимости в получении сверхвысокоточных результатов. Любое число Mathematica может преобразовать в менее точное, но адекватное для дальнейших вычислений. Для этих целей в программе содержится целый ряд встроенных функций.
Функция Round[expr] по правилам математики округляет число expr до ближайшего целого. Её расширенный вариант Round[expr,a] округляет expr до ближайшего числа, нацело делящегося на a. При этом ни expr, ни a не обязаны быть целыми: они могут быть и вещественными, и рациональными, и даже комплексными. На рис. 4.18 см. примеры In[1] и In[2] использования функции округления Round.
Округление в обход математических правил позволяют совершить функции Floor и Ceiling. Первая, заданная в виде Floor[expr], возвращает ближайшее целое число, меньшее или равное expr, а Ceiling[expr] — ближайшее целое число, большее или равное expr. Расширенная форма Floor[expr,a] возвращает ближайшее число, нацело делящееся на a и меньшее expr. Соответственно, Ceiling[expr,a] возвращает ближайшее число, нацело делящееся на a и большее expr. In[3] и In[4] рис. 4.18 см. — примеры использования функций Floor и Ceiling.
Частично роль Floor берёт на себя функция IntegerPart. Заданная в единственной своей форме IntegerPart[expr] она возвращает целую часть выражения expr (пример In[5] на рис. 4.18).
Любое вещественное число expr может быть преобразовано в рациональное или целое при помощи функции Rationalize[expr] (пример In[6] на рис. 4.18).
Последней в этой лекции представим любопытную функцию Divisible[a,b], которая проверяет, делится ли нацело число a на число b, и в зависимости от результата возвращает True или False — см. пример In[7] на рис. 4.18. Функция Divisible работает корректно только в случае, если a и b являются целыми или рациональными.
Подробней об округлении чисел см. книгу Е. М. Воробьёва [1, с. 67–68].
Ключевые термины
Разреженный массив — массив, в котором не все элементы используются, имеются в наличии или нужны в данный момент
Разрядность — количество значащих десятичных цифр, используемых Mathematica в представлении вещественных чисел при вычислениях.
Точность — число значащих десятичных цифр, используемых для представления дробной части вещественных чисел.
Уплотнённый массив в Mathematica — список однотипных (целые, вещественные, комплексные) чисел.
Краткие итоги
В данной лекции мы подробно познакомились с особенностями представления в Mathematica численных данных разных типов. Мы научились задавать численные данные в разных системах счисления, преобразовывать числа из одной СС в другую. Мы научились задавать и использовать случайные числа. Мы познакомились с понятиями разрядности и точности числа, узнали, каким образом Mathematica работает с приближёнными числами, научились узнавать точность и разрядность результатов вычислений и при необходимости самостоятельно задавать их. Мы научились оптимизировать ресурсоёмкие расчёты при помощи использования разреженных и уплотнённых массивов. Также мы познакомились с функциями округления приближённых чисел.
Вопросы
- Назовите типы численных данных, с которыми работает Mathematica. Какие из них рассматриваются программой как точные? приближённые?
- Каким образом узнать/проверить принадлежность числа к тому или иному типу данных?
- В чём заключается "двойственность" именованных констант?
- С числами в какой системе счисления Mathematica работает по умолчанию? К СС с какими основаниями Mathematica позволяет преобразовывать числа?
- Назовите функцию Mathematica, предназначенную для генерации случайных чисел. В какой форме и могут быть заданы её аргументы?
- Что в Mathematica понимается под разрядностью и точностью числа? Какие функции позволяют узнать разрядность и точность, с которыми задано число? Каковы разрядность и точность целых и рациональных чисел?
- В каком случае вещественное число имеет машинную разрядность?
- Каким образом определяются точность и разрядность чисел? Почему они не всегда принимают целые значения?
- Какие объекты Mathematica называются разреженными и уплотнёнными массивами? В каких случаях их следует использовать?
- Какие функции используются для задания разреженных и уплотнённых массивов?
- Назовите основные функции Mathematica для округления чисел.
Упражнения
- На комплексной плоскости заданы комплексные числа
- Не пользуясь функциями Abs и Arg, найдите их абсолютные значения и углы наклона заданных ими радиус-векторов. При помощи Abs и Arg проверьте результаты, определите, к какому типу численных данных они принадлежат.
- Не пользуясь функцией Conjugate, запишите числа, комплексно сопряжённые заданным.
-
- запишите вещественное число, целой частью которого является день, а дробной — месяц вашего рождения;
- переведите заданное число в двоичную СС;
- полученное в пункте (а) число переведите в СС с основанием 19.
-
- задайте число, содержащее цифры даты вашего рождения, записанной в формате ддммгггг;
- создайте список, элементами которого будут цифры числа, полученного в предыдущем пункте, в десятичной СС;
- то же, что и в (б), но в СС с основанием 9;
- попробуйте создать список, что и в (б), в СС с основанием 40.
- Создайте одномерный список, содержащий от семи до одиннадцати элементов. Число элементов задаётся случайным образом из указанного диапазона. Элементы списка при этом
- случайным образом должны принимать значения +7, 0 и -7;
- +7 и -7;
- а, b и c;
- случайным образом должны принимать вещественные значения из диапазона от 0 до 1 или целые значения от 2 до 45.
- Выясните, на какое число следует умножить/разделить число expr, заданное как expr=N[e^Pi,30], чтобы
- точность полученного результата превысила разрядность, по крайней мере, на 5;
- на величину, меньшую единицы;
- разрядность превышала точность не более чем на 5.
-
- создайте разреженный массив 8x8, на главной диагонали которого поместите цифры даты вашего рождения, на диагональ выше главной — число 99, на диагональ ниже главной — число 55, в остальные ячейки — число 77;
- представьте полученный в предыдущем пункте массив графически, раскрасив его при помощи одной из стандартных цветовых схем Mathematica.
- Применив в произвольном порядке к числу 6.2 функции Round, Floor, Ceiling, IntegerPart и Rationalize, получите число 9. Осуществите обратную операцию, получив 6.2 из 9. Выполните то же задание для любой пары чисел из следующего ряда: 1.1, 2.56, 3, 3.9, 9/5, 4.75, 5.25, 6., 6.3, 7.23, 8.4, 8.5, 9.9.