Get next or prior single precision value MATLAB function ?
조회 수: 15 (최근 30일)
이전 댓글 표시
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
채택된 답변
James Tursa
2019년 8월 12일
편집: James Tursa
2019년 8월 12일
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
Steven Lord
2021년 1월 26일
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
2021년 1월 26일
편집: Stephen23
2021년 1월 26일
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?
추가 답변 (0개)
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!