Get next or prior single precision value MATLAB function ?
15 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Firan Lucian
el 12 de Ag. de 2019
Is there a MATLAB function for next or prior float32 number ?
(similar to nextafterf, nexttowardf or float_next, float_prior)
tried these functions:
function [out] = next_SP(val)
% Get next after SP value - float32, single precision
% Increment float with smalllest step, SP representable
% TODO check for sign changes, domain INF NAN subnormals changes,
% uint32 ovf realmax + 1, mantissa exp changes
% Check nextafterf from math.h
% The nextafter() functions return the next representable floating-point
% value following x in the direction of y. If y is less than x, these
% functions will return the largest representable number less than x.
% If x equals y, the functions return y.
% https://www.boost.org/doc/libs/1_46_1/libs/math/doc/sf_and_dist/html/math_toolkit/utils/next_float/float_next.html
% Returns the next representable value which is greater than x.
% If x is non-finite then returns the result of a domain_error.
% If there is no such value greater than x then returns an overflow_error.
int_v = typecast(single(val), 'uint32' );
%disp([ 'Init ' num2str(single(val)) ' 0x' num2hex(single(val)) ', ' dec2bin(int_v, 32) ]);
int_v = int_v + 1;
out = typecast(uint32(int_v), 'single' );
%disp([ 'Init ' num2str(out) ' 0x' num2hex(out) ', ' dec2bin(int_v, 32) ]);
end
and
function [out] = prior_SP(val)
% Get next before SP value - float32, single precision
% Decrement float with smalllest step, SP representable
% TODO check for sign changes, domain INF NAN subnormals changes,
% uint32 udf realmax + 1, mantissa exp changes
% Check nexttowardf from math.h
% https://www.boost.org/doc/libs/1_48_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/next_float/float_prior.html
% Returns the next representable value which is less than x.
% If x is non-finite then returns the result of a domain_error.
% If there is no such value less than x then returns an overflow_error.
int_v = typecast(single(val), 'uint32' );
%disp([ 'Init ' num2str(single(val)) ' 0x' num2hex(single(val)) ', ' dec2bin(int_v, 32) ]);
int_v = int_v - 1;
out = typecast(uint32(int_v), 'single' );
%disp([ 'Init ' num2str(out) ' 0x' num2hex(out) ', ' dec2bin(int_v, 32) ]);
end
nexttoward_SP(-0)
Init 0 0x80000000, 10000000000000000000000000000000
Init NaN 0x7fffffff, 01111111111111111111111111111111
nexttoward_SP(0)
Init 0 0x00000000, 00000000000000000000000000000000
Init 0 0x00000000, 00000000000000000000000000000000
nexttoward_SP(-inf)
Init -Inf 0xff800000, 11111111100000000000000000000000
Init -3.402823466385289e+38 0xff7fffff, 11111111011111111111111111111111
nexttoward_SP(Inf)
Init Inf 0x7f800000, 01111111100000000000000000000000
Init 3.402823466385289e+38 0x7f7fffff, 01111111011111111111111111111111
nexttoward_SP(nan)
Init NaN 0xffc00000, 11111111110000000000000000000000
Init NaN 0xffbfffff, 11111111101111111111111111111111
(maybe similar for half or double precision)
5 comentarios
Respuesta aceptada
James Tursa
el 12 de Ag. de 2019
Editada: James Tursa
el 12 de Ag. de 2019
The designers of IEEE floating point were brilliant. The next largest value (in magnitude) is always obtained by just adding 1 to the underlying integer bit pattern. When the integer value rolls over into the mantissa part, guess what ... that’s the correct result. When the value reaches realmax and you add 1 to the underlying integer, guess what ... you get the correct result of inf. Brilliant! The issues of 0 crossings and NaN have already been noted by Walter. You will have to decide for yourself what the various NaN bit patterns mean for your application.
12 comentarios
Steven Lord
el 26 de En. de 2021
format hex
x = 3
y = x + eps(x)
Note that x and y differ only in the last bit.
z = realmax
w = z + eps(z)
isinf(w)
Stephen23
el 26 de En. de 2021
Editada: Stephen23
el 26 de En. de 2021
The original question specifies single type:
format hex
x = single(3)
y = x + eps(x)
However this does not completely answer the question, which as well as the next value also requests the previous value. As far as I can tell, the previous value can be obtained like this (for positive values):
x = flintmax('single')
z = x - eps(x-eps(x)) % correct
z = x - eps(x) % incorrect
As far as I can tell, previous negative values only require this:
x = -flintmax('single')
y = x - eps(x)
By symmetry this implies that the next negative value would actually be given by:
y = x + eps(x+eps(x)) % correct
y = x + eps(x) % incorrect
This is just me thinking aloud... please feel free to continue / comment. Is there a neat way to combine the 4 cases?
Más respuestas (0)
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!