Ответ
Вид. Существует недокументированный вызов функции feature('setround')
, который вы можете использовать для получения или установки режима округления, используемого Matlab.
Итак, это может быть сделано, но вы не должны этого делать. :)
ВНИМАНИЕ: это недокументированная, неподдерживаемая функция! Используйте на свой страх и риск!
Этот feature('setround')
поддерживает 4 из 5 режимов округления IEEE-754: есть только один «ближайший» режим, и я не знаю, «привязан ли он к четному» или «связан с нулем».
Поддерживаемые режимы:
feature('setround')
- Получить текущий режим округления
feature('setround', 0.5)
- округлить до ближайшего (не знаю, связано ли оно с четным или нулевым)
feature('setround', Inf)
- округление вверх (в сторону + Inf)
feature('setround', 0)
- округлить до нуля
feature('setround', -Inf)
- округлить вниз (в сторону -Inf)
Примечание по тестированию: режим округления IEEE-754 не влияет на round()
и его родственников. Скорее, оно определяет, как арифметические операции ведут себя в пределах точности с плавающей запятой.
Демонстрация
%ROUNDINGEXAMPLE Demonstrates IEEE-754 Rounding Mode control
%
% This uses a completely undocumented and unsupported feature!
% Not for production use!
%% Setup
clear; clc
n = 2000;
X = ones(n)*1E-30; % matrix with n^2 elements
defaultRoundingMode = feature('setround'); % store default rounding mode
%%
feature('setround',0.5);
r1 = prettyPrint('Nearest', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001110101010000011110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001110101010000011110 = 4e-24
%}
%%
feature('setround',-Inf);
r2 = prettyPrint('To -Infinity', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001011100000111000110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001011100000111000110 = 4e-24
%}
%%
feature('setround',Inf);
r3 = prettyPrint('To Infinity', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101010100011101100100001
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101010100011101100100001 = 4e-24
%}
%%
feature('setround',0);
r4 = prettyPrint('To zero', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001011100000111000110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001011100000111000110 = 4e-24
%}
%%
feature('setround',defaultRoundingMode);
r5 = prettyPrint('No accumulated roundoff error', 4e-24);
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101010001000111010100111
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101010001000111010100111 = 4e-24
%}
%% Helper function
function r = prettyPrint(s, r)
fprintf('%s:\n%65.60f\n\n', s, r);
end
Я получаю:
Nearest:
0.000000000000000000000003999999999966490758963870373537264729
To -Infinity:
0.000000000000000000000003999999999789077070014108839608005726
To Infinity:
0.000000000000000000000004000000000118618095059505975310731249
To zero:
0.000000000000000000000003999999999789077070014108839608005726
No accumulated roundoff error:
0.000000000000000000000003999999999999999694801998206811298525
Подтверждения
Спасибо Райану Клотсу из Технической поддержки MathWorks за то, что он прямо мне помог и предоставил хороший демонстрационный код!