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

Компьютеры имеют ограниченный объем памяти. Поэтому существует и предел того, насколько большим может быть число, представленное в памяти. Также существует и ограничение на то, насколько малым может быть абсолютное значение ненулевого числа.

Конечность памяти означает, что переменная MATLAB не может хранить иррациональное число. Поэтому, например, функция pi возвращает не число пи, а только приближение, как и функция квадратного корня может вернуть только приближенное значение квадратного корня из двух.

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

Рассмотрим пример:

x = 17;
class(x)
ans =
    'double'

Функция class сообщает нам, что x имеет тип double. Это тип данных по умолчанию для всех числовых данных в MATLAB. Это относится не только к переменным, но и к значениям.

class(23)
ans =
    'double'

Почему функция называется class, а не type? Оказывается type зарезервирована для команды, которая выводит содержимое файла (в смысле “type the file”).

Рассмотрим ещё один пример:

class(sqrt(-1))
ans =
    'double'

Хотя результат является мнимым числом и в то же время MATLAB поддерживает комплексные числа, он не разделяет их на действительные, мнимые и комплексные, когда классифицирует их по типам.

Давайте рассмотрим функцию whos:

whos
Name       Size            Bytes  Class     Attributes
  ans       1x6                12  char                
  x         1x1                 8  double              

В столбце size указаны размеры массива, подробнее о массивах мы поговорим позже. В MATLAB все скаляры рассматриваются как массивы 1x1.

Значение ans - это строка, символами которой являются 'd', 'o', 'u', 'b', 'l', 'e'. А как значение ans стало строкой? Это произошло еще в этой команде class(sqrt(-1)). Это была последняя команда, в которой мы не присваивали вывод переменной. Команда class вернула тип данных вывода квадратного корня. Им оказался double. И вернула она эту информацию в виде строки.

Конечно, когда мы вводим строку, как, например, при вводе строки формата в операторе fprintf, мы должны заключить ее в кавычки, чтобы MATLAB знал, что это не имя переменной. Когда же MATLAB печатает строку, он не заключает ее в кавычки.

Говоря о заключении строк в кавычки, давайте посмотрим на тип вводимой строки.

class('Hello')
ans =
    'char'

Снова char, как и ожидалось для символьной строки.

Числовые типы

Тип double представляет числа в формате “с плавающей точкой”, что можно сравнить с научной нотацией. Например, число \(12.34\) в научной нотации записывается как \(1.234 \cdot 10^{-2}\), что позволяет хранить его как два целых числа: 1234 и \(-2\). При использовании представления с плавающей точкой и двойной точностью выделяется 64 бита памяти (или 8 байт), где 1 бит отведён для знака, 52 бита для мантиссы и 11 бит для экспоненты. Мантисса, схожа с числом \(1.234\) в научной нотации, по определению всегда меньше единицы, и первая значащая цифра после запятой не может быть нулём, например, \(12.34 \rightarrow 0.1234\).

Точность математических операций определяется наименее значащим битом мантисс операндов. Эта точность обозначается числом \(\varepsilon\). Например: \(1.0 + \delta = 1.0\), если \(\vert \delta \vert < \varepsilon\). Величина \(\varepsilon\) доступна в MATLAB через встроенную переменную eps.

Единственным другим типом с плавающей точкой, поддерживаемым в MATLAB, является single, который содержит всего 32 бита. Название double (двойной) происходит от того, что этот тип занимает в два раза больше памяти, чем single (одинарный). Благодаря этому дополнительному пространству, double позволяет обрабатывать числа с большей точностью, отсюда и термин ‘double precision’ — числа с двойной точностью.

Что делать, если вам нужны только целые числа? Например, значения, получаемые от датчиков или значения цвета пикселей при обработке изображений, обычно представляют собой целые числа. В MATLAB есть поддержка множества различных целочисленных типов данных — всего восемь. Среди них четыре знаковых и четыре беззнаковых типа.

Ещё один ключевой аспект целочисленных типов — это их разрядность. В MATLAB доступны 8-, 16-, 32- и 64-битные целочисленные типы, как знаковые, так и беззнаковые. Большее количество битов увеличивает диапазон представляемых чисел, позволяя обрабатывать более широкий спектр данных.

В следующей таблице представлены все числовые типы MATLAB и диапазоны, которые они охватывают.

Тип данных Диапазон значений
int8 \(-2^{7}\) до \(2^7 - 1\)
int16 \(-2^{15}\) до \(2^{15} - 1\)
int32 \(-2^{31}\) до \(2^{31} - 1\)
int64 \(-2^{63}\) до \(2^{63} - 1\)
uint8 \(0\) до \(2^{8} - 1\)
uint16 \(0\) до \(2^{16} - 1\)
uint32 \(0\) до \(2^{32} - 1\)
uint64 \(0\) до \(2^{64} - 1\)
single \(-3.4 \times 10^{38}\) до \(3.4 \times 10^{38}\), Inf, NaN
double \(-1.79 \times 10^{308}\) до \(1.79 \times 10^{308}\), Inf, NaN

Inf («бесконечность») чаще всего возникает при делении ненулевого числа на ноль. Это значение превышает максимально допустимый предел, который может быть представлен в типе данных double. Аналогично работает и -Inf, обозначающий отрицательную бесконечность.

Ещё одно специальное значение, которое может принимать тип данных single или double, — это NaN («не число»). NaN используется для обозначения результатов вычислений, которые не приводят к допустимым числовым значениям. Примером такой операции может служить деление нуля на ноль.

Рассмотрим некоторые полезные функции

Проверка типа:

isa(x, 'double')

Функция isa проверяет, соответствует ли тип данных переменной x указанному типу. В данном случае возвращает true, если x имеет тип double, и false — в противном случае

Проверка диапазона:

Функции intmax и intmin дают максимальное и минимальное значение целочисленных типов:

intmax
ans =
  int32
   2147483647
ans =
  int32
   -2147483648

Также можно передать аргумент, например: intmax('int64') -> 9223372036854775807.

Функции realmax и realmin дают максимальное и минимальное значение для типов с плавающей точкой:

realmax
ans =
  1.7977e+308
realmin
ans =
  2.2251e-308

Также можно передать аргумент, например: realmin('single') -> 1.1755e-38.

В дополнение к функциям проверки типов, MATLAB предлагает набор функций для их преобразования. Название каждой функции совпадает с желаемым типом данных, например: int8(x), uint32(x), double(x) и так далее.

Конечно, самое частое действие с переменными в MATLAB — это арифметические операции, и существуют правила арифметики, зависящие от типов данных. Все арифметические операции без проблем принимают два операнда одного типа, и результат всегда имеет тот же тип.

MATLAB также позволяет смешивать типы данных в арифметических выражениях. Это называется арифметикой смешанного типа (mixed-mode arithmetic), и существует множество правил и ограничений относительно того, что допустимо и какого типа будет результат. Эти правила могут быть довольно сложными и обременительными, поэтому мы не будем углубляться в них здесь.

В то же время, есть хорошие новости: операторы сравнения работают с любым сочетанием числовых типов данных без проблем. И неудивительно, что результат всегда имеет один тип — logical.

x = single(43.23);
a = int8(-16);
b = uint16(1234);
whosdigit to the right of the decimal point is not zero.
  Name      Size            Bytes  Class     Attributes
  a         1x1                 1  int8                
  b         1x1                 2  uint16              
  x         1x1                 4  single   

Что, если мы попытаемся присвоить число, которое не вписывается в заданный тип?

k = uint8(500)
k =
  uint8
   255
k = uint8(256)
k =
  uint8
   255
k = uint8(-1)
k =
  uint8
   0

Функция преобразования выдает число, наиболее близкое к входному значению, которое может быть представлено в данном типе данных. Здесь мы работаем с типом данных unit8, который может содержать значения от 0 до 255.

Следует соблюдать осторожность при переприсваивании значений:

k = 2;
class(k)
ans =
    'double'

В тот момент, когда мы присвоили 2 числу k, его тип данных изменился. Число 2 по умолчанию имеет тип double.

Такое поведение логично, поскольку если бы мы присвоили k строку, мы бы не ожидали, что она будет иметь какой-либо другой тип данных.

k = 'Hello World!';
class(k)
ans =
    'char'

В MATLAB переменная автоматически принимает тип присваиваемого значения. Во многих других языках программирования переменные объявляются с фиксированным типом, который сохраняется на всё время использования. В таких языках программирования попытка присвоить значение переменной типа char другой переменной, например k, может привести к ошибке или вызвать неявное преобразование типа при присваивании.