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

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

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

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

Биты

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

63

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

62 на 52

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

51 на 0

Дробные f числа 1.f

Одноточная плавающая точка

MATLAB создает одинарную точность (или single) тип данных согласно стандарту 754 IEEE для одинарной точности. Любое значение, сохраненное как 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 в структуре. The 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 выполняются в арифметике двойной точности, соответствующей стандарту 754 IEEE. Поскольку компьютеры представляют числа только с конечной точностью (двойная точность вызывает 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 - Операции с плавающей точкой и линейная алгебра

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

Ссылки

[1] Молер, Клеве. «Плавающие точки». Новости и заметки MATLAB. Осень, 1996.

[2] Молер, Клеве. Числовые вычисления с MATLAB. Natick, MA: The MathWorks, Inc., 2004.