MATLAB ® представляет числа с плавающей запятой в формате двойной или одной точности. По умолчанию используется двойная точность, но можно сделать любое число одной точностью с помощью простой функции преобразования.
MATLAB создает двойную точность (или double) тип данных в соответствии со стандартом IEEE ® 754 для двойной точности. Любое значение, сохраненное как double требуется 64 бита, отформатированных, как показано в таблице ниже:
|
Биты |
Использование |
|---|---|
|
|
Знак ( |
|
|
Экспонента, смещенная на |
|
|
Часть |
MATLAB создает единственную точность (или single) тип данных в соответствии со стандартом IEEE 754 для одиночной точности. Любое значение, сохраненное как single требуется 32 бита, отформатированных, как показано в таблице ниже:
|
Биты |
Использование |
|---|---|
|
|
Знак ( |
|
|
Экспонента, смещенная на |
|
|
Часть |
Поскольку MATLAB хранит номера типа single используя 32 бита, они требуют меньше памяти, чем числа типа double, которые используют 64 бита. Однако, поскольку они хранятся с меньшим количеством битов, количество типов single представлены с меньшей точностью, чем числа типа double.
Используйте двойную точность для хранения значений, превышающих приблизительно 3,4 x 1038 или менее приблизительно -3,4 x 1038. Для чисел, лежащих между этими двумя пределами, можно использовать либо двойную, либо одинарную точность, но одиночная требует меньше памяти.
Поскольку числовым типом по умолчанию для MATLAB является double, можно создать double с помощью простого оператора назначения:
x = 25.783;
whos функция показывает, что MATLAB создал массив типа 1 на 1 double для значения, только что сохраненного в x:
whos x Name Size Bytes Class x 1x1 8 double
Использовать isfloat если вы просто хотите проверить, что x - число с плавающей запятой. Эта функция возвращает логический 1 (true), если входной сигнал является числом с плавающей запятой, и логический 0 (false) в противном случае:
isfloat(x) ans = logical 1
С помощью функции MATLAB можно преобразовать другие числовые данные, символы или строки, а также логические данные в двойную точность. double. Этот пример преобразует целое число со знаком в плавающую точку с двойной точностью:
y = int64(-589324077574); % Create a 64-bit integer x = double(y) % Convert to double x = -5.8932e+11
Поскольку MATLAB хранит числовые данные как double по умолчанию необходимо использовать single функция преобразования для создания числа с одной точностью:
x = single(25.783);
whos функция возвращает атрибуты переменной x в структуре. bytes поле этой структуры показывает, что, когда x хранится как один, требуется всего 4 байта по сравнению с 8 байтами, чтобы сохранить его как double:
xAttrib = whos('x');
xAttrib.bytes
ans =
4
Можно преобразовать другие числовые данные, символы или строки, а также логические данные в одну точность с помощью single функция. Этот пример преобразует целое число со знаком в плавающую точку с одинарной точностью:
y = int64(-589324077574); % Create a 64-bit integer x = single(y) % Convert to single x = single -5.8932e+11
В этом разделе описываются классы, которые можно использовать в арифметических операциях с числами с плавающей запятой.
Основные арифметические операции можно выполнять с помощью double и любой из следующих других классов. Если один или несколько операндов являются целым числом (скаляром или массивом), double операнд должен быть скаляром. Результат имеет тип double, если не указано иное:
single - Результат имеет тип single
double
int* или uint* - Результат имеет тот же тип данных, что и целочисленный операнд
char
logical
В этом примере выполняется арифметика данных типов char и double. Результат имеет тип double:
c = 'uppercase' - 32; class(c) ans = double char(c) ans = UPPERCASE
Основные арифметические операции можно выполнять с помощью single и любой из следующих других классов. Результат всегда single:
single
double
char
logical
В этом примере по умолчанию 7.5 - тип double, и результат имеет тип single:
x = single([1.32 3.47 5.28]) .* 7.5; class(x) ans = single
Для double и single существует наибольшее и наименьшее число, которое можно представить с помощью этого типа.
Функции MATLAB realmax и realmin возвращает максимальное и минимальное значения, которые можно представить с помощью double тип данных:
str = 'The range for double is:\n\t%g to %g and\n\t %g to %g';
sprintf(str, -realmax, -realmin, realmin, realmax)
ans =
The range for double is:
-1.79769e+308 to -2.22507e-308 and
2.22507e-308 to 1.79769e+308
Числа больше realmax или меньше, чем -realmax присваивают значения положительной и отрицательной бесконечности соответственно:
realmax + .0001e+308 ans = Inf -realmax - .0001e+308 ans = -Inf
Функции MATLAB realmax и realmin, при вызове с аргументом 'single', возвращает максимальное и минимальное значения, которые можно представить с помощью single тип данных:
str = 'The range for single is:\n\t%g to %g and\n\t %g to %g';
sprintf(str, -realmax('single'), -realmin('single'), ...
realmin('single'), realmax('single'))
ans =
The range for single is:
-3.40282e+38 to -1.17549e-38 and
1.17549e-38 to 3.40282e+38Числа больше realmax('single') или меньше, чем -realmax('single') присваивают значения положительной и отрицательной бесконечности соответственно:
realmax('single') + .0001e+038
ans =
single
Inf
-realmax('single') - .0001e+038
ans =
single
-InfЕсли результат арифметического вычисления с плавающей запятой не так точен, как ожидалось, это, вероятно, вызвано ограничениями оборудования компьютера. Вероятно, ваш результат был немного менее точным, потому что аппаратные средства имели недостаточно битов для представления результата с идеальной точностью; поэтому оно усекло результирующее значение.
Поскольку существует только конечное число чисел с двойной точностью, невозможно представить все числа в хранилище с двойной точностью. На любом компьютере имеется небольшой промежуток между каждым числом двойной точности и следующим большим числом двойной точности. Можно определить размер этого промежутка, что ограничивает точность результатов, используя eps функция. Например, чтобы найти расстояние между 5 и следующее большее число двойной точности, введите
format long
eps(5)
ans =
8.881784197001252e-16Это говорит о том, что нет чисел с двойной точностью между 5 и 5 + eps(5). Если вычисление с двойной точностью возвращает ответ 5, результат является точным только для eps(5).
Значение eps(x) зависит от x. Этот пример показывает, что, как x становится больше, как и eps(x):
eps(50)
ans =
7.105427357601002e-15При вводе eps без входного аргумента MATLAB возвращает значение eps(1), расстояние от 1 до следующего большего числа с двойной точностью.
Аналогично, существуют промежутки между любыми двумя числами с одной точностью. Если x имеет тип single, eps(x) возвращает расстояние между x и следующее большее число с одинарной точностью. Например,
x = single(5); eps(x)
прибыль
ans = single 4.7684e-07
Обратите внимание, что этот результат больше, чем eps(5). Поскольку чисел с одной точностью меньше, чем чисел с двойной точностью, промежутки между числами с одной точностью больше, чем промежутки между числами с двойной точностью. Это означает, что результаты арифметики с одной точностью менее точны, чем в арифметике с двойной точностью.
Для числа x типа double, eps(single(x)) дает верхнюю границу для суммы, которая x округляется при преобразовании из double кому single. Например, при преобразовании числа с двойной точностью 3.14 кому single, он округлен на
double(single(3.14) - 3.14) ans = 1.0490e-07
Сумма, которая 3.14 округлено меньше, чем
eps(single(3.14)) ans = single 2.3842e-07
Почти все операции в MATLAB выполняются в арифметике с двойной точностью, соответствующей стандарту IEEE 754. Поскольку компьютеры представляют числа только с конечной точностью (двойная точность требует 52 бита мантиссы), вычисления иногда дают математически неинтуитивные результаты. Важно отметить, что эти результаты не являются ошибками в MATLAB.
Используйте следующие примеры, чтобы определить эти случаи:
Десятичное число 4/3 не является точно представимой как двоичная дробь. По этой причине следующий расчет не дает ноль, а скорее показывает количество eps.
e = 1 - 3*(4/3 - 1) e = 2.2204e-16
Аналогично, 0.1 не является точно представимым как двоичное число. Таким образом, получается следующее неинтуитивное поведение:
a = 0.0; for i = 1:10 a = a + 0.1; end a == 1 ans = logical 0
Обратите внимание, что порядок операций может иметь значение при вычислении:
b = 1e-16 + 1 - 1e-16; c = 1e-16 - 1e-16 + 1; b == c ans = logical 0
Между числами с плавающей запятой имеются промежутки. По мере того, как числа становятся больше, так и промежутки, о чем свидетельствуют:
(2^53 + 1) - 2^53
ans =
0С тех пор pi не является на самом деле δ, это не удивительно, что sin(pi) не совсем равно нулю:
sin(pi)
ans =
1.224646799147353e-16Когда вычитания выполняются с почти равными операндами, иногда отмена может произойти неожиданно. Ниже приведен пример гашения, вызванного болтанием (потеря точности, делающая добавление незначительным).
sqrt(1e-16 + 1) - 1
ans =
0Некоторые функции в MATLAB, такие как expm1 и log1p, может использоваться для компенсации последствий катастрофической отмены.
Округление, отмена и другие черты арифметики с плавающей запятой объединяются для получения поразительных вычислений при решении задач линейной алгебры. MATLAB предупреждает, что следующая матрица A плохо кондиционируется, и, следовательно, система Ax = b может быть чувствительным к небольшим возмущениям:
A = diag([2 eps]);
b = [2; eps];
y = A\b;
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 1.110223e-16.Это лишь несколько примеров, показывающих, как арифметика с плавающей запятой IEEE влияет на вычисления в MATLAB. Следует отметить, что затрагиваются все вычисления, выполняемые в арифметике IEEE 754, включая приложения, написанные на языке C или FORTRAN, а также MATLAB.
[1] Молер, Клеве. «Плавающие точки». Новости и заметки MATLAB. Осень, 1996.
[2] Молер, Клеве. Численные вычисления с MATLAB. Натик, Массачусетс: The MathWorks, Inc., 2004.