Round, With Tie Breakers, Round Two
I published Round, With Ties to Even a couple of days ago. Steve Eddins and Daniel Dolan immediately had substantive comments. Here is my reaction to their comments.
Contents
Two More
The four choices that I described for how to break ties -- 'even', 'odd', 'up' and 'down' -- all have the same behavior for positive and negative numbers. The current built-in round uses the 'up" rule.
Steve sees the need for two more choices that are sensitive to the sign of the number. I will call them 'plus' and 'minus". They round to the right and to the left on the number line. That's sometimes known as round toward plus infinity and toward minus infinity.
Sample
Here's a chart of a few values.
x = (-4.5:1:4.5)'; xRound(x);
x round up down even odd plus minus -4.500 -5 -5 -4 -4 -5 -4 -5 -3.500 -4 -4 -3 -4 -3 -3 -4 -2.500 -3 -3 -2 -2 -3 -2 -3 -1.500 -2 -2 -1 -2 -1 -1 -2 -0.500 -1 -1 -0 -0 -1 -0 -1 0.500 1 1 0 0 1 1 0 1.500 2 2 1 2 1 2 1 2.500 3 3 2 2 3 3 2 3.500 4 4 3 4 3 4 3 4.500 5 5 4 4 5 5 4
And the plot.
Scaling
The current built-in round also includes the possibility of scaling by a power of 10 to facilitate rounding to, say, the nearest multiple of 1000, or of 1/1000, or three significant figures. Daniel was concerned that having both scaling and tie-breaking options in the same function would be confusing.
But, I think it is OK, because:
- round(x,'even'), the parameter 'even' is a char.
- round(x,3), the parameter 3 is numeric.
- round(x,3,'significant'), the parameter 'significant' is a specific char.
So, the statements
- round(x,'even',3)
- round(x,3,'even')
- round(x,'even',3,'significant')
are unambiguous and distinguishable. After x, the other parameters can be given in any order.
round
Here is my proposal for the enhancement request about round. It is available here.
type round.m
function r = round(varargin) % r = round(x) scales and rounds the elements of x to the nearest integers. % Default: ties, elements halfway between integers, are rounded away from zero. % % r = round(x,'even') ties round to even integers. % r = round(x,'odd') ties round to odd integers. % r = round(x,'up') ties round away from zero (same as default). % r = round(x,'down') ties round towards zero. % r = round(x,'plus') ties round to the right on the number line. % r = round(x,'minus') ties round to the left on the number line. % % r = round(x,n), n >= 0, round(10^n*x)/10^n, round(12.3456,2) = 12.3500 % r = round(x,-n), n > 0, 10^n*round(x/10^n), round(1234.56,-2) = 1200. % r = round(x,n,'significant'), round(.001234,2,'significant') = .0012 % r = round(x,n,'decimals) same as round(x,n). % % r = round(x,...), ties, n, 'significant' and 'decimals' can be in any order. % % Use Round(...) with capital R to distinguish from built-in round(...). [x,n,ties] = parse_input(varargin{:}); x = prescale(x,n); a = abs(x) + 0.5; r = floor(a); switch ties case 'even' m = (r == a) & (mod(r,2) == 1); case 'odd' m = (r == a) & (mod(r,2) == 0); case 'down' m = (r == a); case 'up' m = []; case 'plus' m = (x < 0) & (r == a); case 'minus' m = (x > 0) & (r == a); otherwise error(['''' ties ''' not recognized.']) end r(m) = r(m) - 1; r = sign(x).*r; r = postscale(r,n); % ---------------------------------------------- function [x,n,ties] = parse_input(varargin) x = varargin{1}; n = zeros(size(x)); ties = 'up'; for k = 2:nargin if isnumeric(varargin{k}) n(:) = varargin{k}; elseif strcmp(varargin{k},'significant') n(:) = n(:) - ceil(log10(abs(x(:)))); elseif strcmp(varargin{k},'decimals') % ignore else ties = varargin{k}; end end end function x = prescale(x,n) if any(n ~= 0) k = n > 0; x(k) = 10.^n(k).*x(k); k = n < 0; x(k) = x(k)./10.^(-n(k)); end end function r = postscale(r,n) if any(n ~= 0) k = n > 0; r(k) = r(k)./10.^n(k); k = n < 0; r(k) = 10.^(-n(k)).*r(k); end end end
댓글
댓글을 남기려면 링크 를 클릭하여 MathWorks 계정에 로그인하거나 계정을 새로 만드십시오.