exponenta event banner

Числа с плавающей запятой

MATLAB ® представляет числа с плавающей запятой в формате двойной или одной точности. По умолчанию используется двойная точность, но можно сделать любое число одной точностью с помощью простой функции преобразования.

Плавающая точка с двойной точностью

MATLAB создает двойную точность (или double) тип данных в соответствии со стандартом IEEE ® 754 для двойной точности. Любое значение, сохраненное как double требуется 64 бита, отформатированных, как показано в таблице ниже:

Биты

Использование

63

Знак (0 = положительное, 1 = отрицательно)

62 кому 52

Экспонента, смещенная на 1023

51 кому 0

Часть f номера 1.f

Плавающая точка с одинарной точностью

MATLAB создает единственную точность (или single) тип данных в соответствии со стандартом IEEE 754 для одиночной точности. Любое значение, сохраненное как single требуется 32 бита, отформатированных, как показано в таблице ниже:

Биты

Использование

31

Знак (0 = положительное, 1 = отрицательно)

30 кому 23

Экспонента, смещенная на 127

22 кому 0

Часть f номера 1.f

Поскольку 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.

Используйте следующие примеры, чтобы определить эти случаи:

Пример 1 - Округление или то, что вы получаете, не то, что вы ожидаете

Десятичное число 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

Пример 2 - Катастрофическая отмена

Когда вычитания выполняются с почти равными операндами, иногда отмена может произойти неожиданно. Ниже приведен пример гашения, вызванного болтанием (потеря точности, делающая добавление незначительным).

sqrt(1e-16 + 1) - 1

ans =
     0

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

Пример 3 - Операции с плавающей точкой и линейная алгебра

Округление, отмена и другие черты арифметики с плавающей запятой объединяются для получения поразительных вычислений при решении задач линейной алгебры. 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.