function x = Round(varargin) % Rounds toward nearest decimal or integer. % % round(x) Round each element of x to the nearest integer. % % round(x, n) Round to the n-th decimal place. % round(x, n, digits="significant") Round to n significant digits. % round(x, n, digits="decimals") Same as round(x,n). % % round(x,..., roundTies="awayFromZero") % round(x,..., roundTies="towardsZero") % round(x,..., roundTies="toOdd") % round(x,..., roundTies="toEven") % round(x,..., roundTies="towardsPlusInfinity") % round(x,..., roundTies="towardsMinusInfinity") % % Ties are rare. round(x,n) is a tie only when 10^n*x is within % roundoff error of a point halfway between two consecutive integers. %_ % Examples % % x = 123456.789 % % round(x) 123457 % round(x,-3) 123000 % round(x,2) 123456.79 % % x = 1.125 % % round(x) 1.000 % round(x,1) 1.100 % round(x,2) 1.130 % round(x,2,roundTies="toEven") 1.120 % round(x,2,roundTies="toOdd") 1.130 % round(x,3) 1.125 % round(x,3,"significant") 1.130 % % x = 1.115 % xlo = 1115/1000 - eps/25 % xhi = 1115/1000 + 24*eps/25 % % round(x,2) 1.120 % round(xlo,2,roundTies="toOdd") 1.110 % round(xhi,2,roundTies="toEven") 1.120 %_ % main program [x,n,sig,tie] = parse(varargin{:}); x0 = x; s = sign(x); x = abs(x); if sig n = n - ceil(log10(x)); else n = n - zeros(size(x)); end x = scale(x,n); z = x; f = z - floor(z); m = (f < 0.5); x(m) = floor(z(m)); m = (f >= 0.5); x(m) = ceil(z(m)); exact = (x0 == single(x0)); if exact t = (f == 0.5); % ties else t = abs(f - 0.5) <= eps(z); % ties end x(t) = ceil(z(t)); switch tie case 'even' m = (mod(x(t),2) == 1); case 'odd' m = (mod(x(t),2) == 0); case 'plus' m = (s(t) < 0); case 'minus' m = (s(t) > 0); case 'zero' m = 1; case 'nan' m = NaN; otherwise m = 0; end x(t) = x(t) - m; x = s.*scale(x,-n); %_ function [x,n,sig,tie] = parse(varargin) x = varargin{1}; n = 0; sig = false; tie = 'from'; for k = 2:nargin vk = varargin{k}; if isnumeric(vk) n = vk; elseif vk == "significant" sig = true; elseif vk == "decimals" || ... vk == "roundTies" || ... vk == "digits" % ignore else tie = char(vk); caps = find(double(tie) < double('a')); if length(caps) > 1 && caps(2) > caps(1)+2 tie = lower(tie(caps(1):caps(2)-1)); elseif length(caps) > 0 && length(tie(caps:end)) <= 5 tie = lower(tie(caps(1):end)); else error(vk + " not recognized.") end end end end %_ function x = scale(x,n) k = (n > 0); x(k) = x(k).*10.^n(k); k = (n < 0); x(k) = x(k)./10.^(-n(k)); end %_ end