MATLAB® представляет числа с плавающей запятой в формате с двойной точностью или с одинарной точностью. Значением по умолчанию является двойная точность, но можно сделать любую одинарную точность номера с простой функцией преобразования.
MATLAB создает с двойной точностью (или double
) тип данных согласно IEEE® Standard 754 для двойной точности. Любое значение, сохраненное как double
требует 64 битов, отформатированных как показано в приведенной ниже таблице:
Биты |
Использование |
---|---|
63 |
Знак ( |
62 |
Экспонента, смещенная |
51 |
Дробный |
MATLAB создает с одинарной точностью (или single
) тип данных согласно Стандарту IEEE 754 для одинарной точности. Любое значение, сохраненное как single
требует 32 битов, отформатированных как показано в приведенной ниже таблице:
Биты |
Использование |
---|---|
31 |
Знак ( |
30 |
Экспонента, смещенная |
22 |
Дробный |
Поскольку 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
число с плавающей запятой. Эта функция возвращает логическую единицу (true
) если вход является числом с плавающей запятой и логическим нолем (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 или ФОРТРАНЕ, а также MATLAB.
[1] Moler, Клив. “Плавающие точки”. Новости MATLAB и примечания. Упадите, 1996.
[2] Moler, Клив. Числовое вычисление с MATLAB. Натик, MA: MathWorks, Inc., 2004.