{"id":7241,"date":"2021-07-25T10:18:41","date_gmt":"2021-07-25T14:18:41","guid":{"rendered":"https:\/\/blogs.mathworks.com\/cleve\/?p=7241"},"modified":"2021-07-25T10:18:41","modified_gmt":"2021-07-25T14:18:41","slug":"round-with-tie-breakers-a-prototype","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/cleve\/2021\/07\/25\/round-with-tie-breakers-a-prototype\/","title":{"rendered":"Round, With Tie Breakers, A Prototype"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p>In February and March I published three blog posts about an enhancement request for MATLAB concerning tie breakers with the <tt>round<\/tt> function, including the ability to round ties to even. <a href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/02\/25\/round-with-ties-to-even\/\">Round One<\/a>, <a href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/03\/02\/round-with-tie-breakers-round-two\/\">Round Two<\/a> and <a href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/03\/08\/round-with-tie-breakers-round-three\/\">Round Three<\/a>.  Since then, a group of us at MathWorks, organized by my colleague (and academic great-great-grand-descendant) Heiko Weichelt, have been considering the request.  We had a virtual design review recently.  This post describes a prototype incorporating the features that were discussed at that review.<\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#19cbb53f-6d60-4e75-a0c4-8f3421cfab48\">round<\/a><\/li><li><a href=\"#86f44c15-a4c8-4a90-92cc-ac17a44647d2\">floor and ceil<\/a><\/li><li><a href=\"#7b83554c-c45c-4e02-9b29-b7f0e8473a8c\">Ties<\/a><\/li><li><a href=\"#f84d69cf-b490-4544-b75f-332addca5880\">Nearest decimal<\/a><\/li><li><a href=\"#9da80548-cf57-4ce8-af79-0f108bd1d942\">IEEE 754<\/a><\/li><li><a href=\"#ba8d5fdb-4d3f-4bef-a662-935256de3d23\">Name-value pairs<\/a><\/li><li><a href=\"#e0e8057a-cfc6-4a04-ad90-ba7cbc79b372\">Not-a-Number<\/a><\/li><li><a href=\"#144f0f7f-24f5-47da-a25c-394c1aacd54d\">help<\/a><\/li><li><a href=\"#971e5884-b8f5-4428-aff4-44d6fa2f6dc6\">examples<\/a><\/li><li><a href=\"#025364d3-6698-4452-aca1-d3601edfb600\">main<\/a><\/li><li><a href=\"#1df88155-b03f-4b7a-94eb-9dbb572107b8\">parse<\/a><\/li><li><a href=\"#4fa30978-6e77-41e1-a2a3-b2815a7affa9\">scale<\/a><\/li><li><a href=\"#bb4d8214-7f22-4336-87f2-eff7f3e584af\">graphic<\/a><\/li><li><a href=\"#f03a7fa1-940f-45af-8382-5fff27dc0f36\">software<\/a><\/li><\/ul><\/div><h4>round<a name=\"19cbb53f-6d60-4e75-a0c4-8f3421cfab48\"><\/a><\/h4><p>Traditionally, <tt>help round<\/tt> had only one line.<\/p><pre>  ROUND(X) rounds each element of X to the nearest integer.<\/pre><p>A few years ago, two optional arguments were added.<\/p><pre>  ROUND(X, N), for positive integers N, rounds to N digits to the right\r\n  of the decimal point. If N is zero, X is rounded to the nearest integer.\r\n  If N is less than zero, X is rounded to the left of the decimal point.\r\n  N must be a scalar integer.<\/pre><pre>  ROUND(X, N, 'significant') rounds each element to its N most significant\r\n  digits, counting from the most-significant or left side of the number.\r\n  N must be a positive integer scalar.<\/pre><h4>floor and ceil<a name=\"86f44c15-a4c8-4a90-92cc-ac17a44647d2\"><\/a><\/h4><p>The functions <tt>floor<\/tt> and <tt>ceil<\/tt> have important roles in any discussion of rounding.  Every real number, <tt>x<\/tt>, that is not an integer, lies between two integers,<\/p><pre>  floor(x) &lt; x &lt; ceil(x) = floor(x) + 1<\/pre><p>If <tt>x<\/tt> is an integer, then<\/p><pre>  floor(x) = x = ceil(x)<\/pre><p>The function <tt>floor(x)<\/tt> defines \"rounding <tt>x<\/tt> towards minus infinity\" and the function <tt>ceil(x)<\/tt> is \"rounding <tt>x<\/tt> towards plus infinity\".<\/p><p>The function <tt>fix(x)<\/tt>, which is also known as \"integer part of <tt>x<\/tt>\", is<\/p><pre>  fix(x) = floor(x) if x &gt;= 0,\r\n         = ceil(x) if x &lt; 0.<\/pre><p>The \"fractional part of <tt>x<\/tt>\" is<\/p><pre>  frac(x) = x - fix(x).<\/pre><p>Two examples<\/p><pre>  x = 9.64             x = -9.64\r\n  floor(x) = 9         floor(x) = -10\r\n  ceil(x) = 10         ceil(x) = -9\r\n  fix(x) = 9           fix(x) = -9\r\n  frac(x) = 0.64       frac(x) = -0.64<\/pre><h4>Ties<a name=\"7b83554c-c45c-4e02-9b29-b7f0e8473a8c\"><\/a><\/h4><p>The traditional code for <tt>round(x)<\/tt> is one line.<\/p><pre>  round(x) = sign(x).*floor(abs(x) + 0.5)<\/pre><p>This implies that<\/p><pre>  round(x) = floor(x) if frac(x) &lt; 0.5\r\n           = ceil(x) if frac(x) &gt; 0.5<\/pre><p>This unambiguously defines <tt>round(x)<\/tt> for almost all <tt>x<\/tt>. The only ambiguous situations are the <i>rounding ties<\/i>. They occur when the fractional part of <tt>x<\/tt> is exactly 1\/2, or 0.5 in decimal.  Ties are relatively rare. Traditionally, MATLAB has rounded ties away from zero.<\/p><p>When there is no scaling specified, the ties are the numbers exactly halfway between two consecutive integers,<\/p><pre>  halfs = -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, ...<\/pre><p>The \"round ties away from zero\" rule produces<\/p><pre>  round(halfs) = -4, -3, -2, -1, 1, 2, 3, 4, ...<\/pre><p>Recently, there has been some interest in alternatives to this behavior.  One alternative is \"round ties to nearest even\". For the halfway numbers, this would be<\/p><pre>  halfs_even = -4, -2, -2, 0, 0, 2, 2, 4, ...<\/pre><h4>Nearest decimal<a name=\"f84d69cf-b490-4544-b75f-332addca5880\"><\/a><\/h4><p>Here are four examples of rounding to the nearest decimal value.<\/p><pre class=\"codeinput\">    format <span class=\"string\">short<\/span>\r\n    format <span class=\"string\">compact<\/span>\r\n<\/pre><div><ul><li>Express intercity mileage distance in whole numbers.  The distance from my home office to MathWorks headquarters is 406.3 miles. What is this to the nearest mile?<\/li><\/ul><\/div><pre class=\"codeinput\">    miles = Round(406.3)\r\n<\/pre><pre class=\"codeoutput\">miles =\r\n   406\r\n<\/pre><div><ul><li>The patient's body temperature is 98.64 degrees. Express this in nearest tenths of a degree.<\/li><\/ul><\/div><pre class=\"codeinput\">    temp = Round(98.64,1)\r\n<\/pre><pre class=\"codeoutput\">temp =\r\n   98.6000\r\n<\/pre><div><ul><li>Express monetary values in hundredths.  The computed interest is 13.8327 Euros.  Express this in hundredths of a Euro.<\/li><\/ul><\/div><pre class=\"codeinput\">    cents = Round(13.8327,2)\r\n<\/pre><pre class=\"codeoutput\">cents =\r\n   13.8300\r\n<\/pre><div><ul><li>The population of Tallahassee in 2019 was reported to be 194,500. What is this to the nearest one-thousand people?<\/li><\/ul><\/div><pre class=\"codeinput\">    pop = Round(194500,-3)\r\n<\/pre><pre class=\"codeoutput\">pop =\r\n      195000\r\n<\/pre><p>Only one of these examples involves a tie.  With a round-ties-to-even rule, the population of Tallahassee would be listed as 194,000 instead of 195,000.<\/p><h4>IEEE 754<a name=\"9da80548-cf57-4ce8-af79-0f108bd1d942\"><\/a><\/h4><p>The <tt>round<\/tt> function is not the same as the round-to-even setting for IEEE 754 floating point arithmetic.  The <tt>round<\/tt> function is done with software by MATLAB; its input is doubles (or singles) and the output is flints (floating point numbers whose values are integers.) The IEEE 754 setting is done in hardware, its input is extended precision or registers with guard bits and its output is doubles that are rarely flints.<\/p><h4>Name-value pairs<a name=\"ba8d5fdb-4d3f-4bef-a662-935256de3d23\"><\/a><\/h4><p>Several reviewers preferred name-value pairs.  Name-value pairs have been part of MATLAB syntax for a long time and a recent enhancement involves the use of an equals sign to specify them. For example<\/p><pre>  plot(x,y,'ko','markersize',10)<\/pre><p>can now be written<\/p><pre>  plot(x,y,marker='o',color='black',markersize=10)<\/pre><p>The left hand portion of a name-value pair is the <tt>paramName<\/tt> and the list of possible right hand portions is <tt>paramValues<\/tt>.<\/p><p>At first, I was not enthusiastic about using a name-value pair for tie-braking in <tt>round<\/tt>.  But after working on this prototype and blog post, I am now in favor.  The <tt>paramName<\/tt> could be<\/p><pre>   roundTies<\/pre><p>There would be six possible <tt>paramValues<\/tt>.<\/p><pre>   awayFromZero\r\n   towardZero\r\n   toEven\r\n   toOdd\r\n   towardPlusInfinity\r\n   towardMinusInfinity<\/pre><p>For example<\/p><pre class=\"codeinput\">    x = (0.1:0.2:0.9)'\r\n    r_from = Round(x,roundTies=<span class=\"string\">'awayFromZero'<\/span>)\r\n    r_even = Round(x,roundTies=<span class=\"string\">'toEven'<\/span>)\r\n<\/pre><pre class=\"codeoutput\">x =\r\n    0.1000\r\n    0.3000\r\n    0.5000\r\n    0.7000\r\n    0.9000\r\nr_from =\r\n     0\r\n     0\r\n     1\r\n     1\r\n     1\r\nr_even =\r\n     0\r\n     0\r\n     0\r\n     1\r\n     1\r\n<\/pre><h4>Not-a-Number<a name=\"e0e8057a-cfc6-4a04-ad90-ba7cbc79b372\"><\/a><\/h4><p>This occurred to me while writing this post. How about a seventh choice for handling ties?<\/p><pre class=\"codeinput\">    r_nan = Round(x,roundTies=<span class=\"string\">'toNaN'<\/span>)\r\n<\/pre><pre class=\"codeoutput\">r_nan =\r\n     0\r\n     0\r\n   NaN\r\n     1\r\n     1\r\n<\/pre><h4>help<a name=\"144f0f7f-24f5-47da-a25c-394c1aacd54d\"><\/a><\/h4><p>The next five sections are the code for a prototype. The file name is <tt>Round.m<\/tt> with a capital <tt>R<\/tt> so we can also access the <tt>round<\/tt> function from the current release. The code is available here: <a href=\"https:\/\/blogs.mathworks.com\/cleve\/files\/Round-1.m\">Round.m<\/a><\/p><pre class=\"codeinput\">    code = split(string(fileread(<span class=\"string\">'Round.m'<\/span>)),<span class=\"string\">'%_'<\/span>);\r\n<\/pre><p>The help text is concise.<\/p><pre class=\"codeinput\">    disp(code(1))\r\n<\/pre><pre class=\"codeoutput\">function x = Round(varargin)\r\n% Rounds toward nearest decimal or integer.\r\n%\r\n% round(x)  Round each element of x to the nearest integer.\r\n%\r\n% round(x, n)  Round to the n-th decimal place.\r\n% round(x, n, digits=\"significant\")  Round to n significant digits.\r\n% round(x, n, digits=\"decimals\")  Same as round(x,n). \r\n% \r\n% round(x,..., roundTies=\"awayFromZero\")\r\n% round(x,..., roundTies=\"towardsZero\")\r\n% round(x,..., roundTies=\"toOdd\") \r\n% round(x,..., roundTies=\"toEven\")\r\n% round(x,..., roundTies=\"towardsPlusInfinity\")           \r\n% round(x,..., roundTies=\"towardsMinusInfinity\")         \r\n%\r\n% Ties are rare. round(x,n) is a tie only when 10^n*x is within\r\n% roundoff error of a point halfway between two consecutive integers.\r\n\r\n<\/pre><h4>examples<a name=\"971e5884-b8f5-4428-aff4-44d6fa2f6dc6\"><\/a><\/h4><p>The help text continues with a few examples.<\/p><pre class=\"codeinput\">    disp(code(2))\r\n<\/pre><pre class=\"codeoutput\">\r\n% Examples\r\n% \r\n%    x = 123456.789\r\n%\r\n%    round(x)     123457\r\n%    round(x,-3)  123000\r\n%    round(x,2)   123456.79\r\n% \r\n%    x = 1.125\r\n%    \r\n%    round(x)                       1.000\r\n%    round(x,1)                     1.100\r\n%    round(x,2)                     1.130\r\n%    round(x,2,roundTies=\"toEven\")  1.120 \r\n%    round(x,2,roundTies=\"toOdd\")   1.130\r\n%    round(x,3)                     1.125\r\n%    round(x,3,\"significant\")       1.130\r\n%\r\n%    x = 1.115 \r\n%    xlo = 1115\/1000 - eps\/25\r\n%    xhi = 1115\/1000 + 24*eps\/25\r\n%\r\n%    round(x,2)                       1.120\r\n%    round(xlo,2,roundTies=\"toOdd\")   1.110\r\n%    round(xhi,2,roundTies=\"toEven\")  1.120\r\n\r\n<\/pre><h4>main<a name=\"025364d3-6698-4452-aca1-d3601edfb600\"><\/a><\/h4><p>Here is the body of <tt>Round<\/tt>.  The numerically sensitive portions are the definition of <tt>exact<\/tt> and the choice of <tt>&lt;<\/tt> or <tt>&lt;=<\/tt> in the determination of <tt>t<\/tt>, the ties.<\/p><pre class=\"codeinput\">    disp(code(3))\r\n<\/pre><pre class=\"codeoutput\">\r\n%   main program\r\n\r\n    [x,n,sig,tie] = parse(varargin{:});\r\n    x0 = x;\r\n    s = sign(x);\r\n    x = abs(x);\r\n    \r\n    if sig\r\n        n = n - ceil(log10(x));\r\n    else\r\n        n = n - zeros(size(x));\r\n    end\r\n    \r\n    x = scale(x,n);\r\n    z = x;\r\n    f = z - floor(z);\r\n    \r\n    m = (f &lt; 0.5);\r\n    x(m) = floor(z(m));\r\n    \r\n    m = (f &gt;= 0.5);\r\n    x(m) = ceil(z(m));\r\n    \r\n    exact = (x0 == single(x0));\r\n    if exact\r\n        t = (f == 0.5);  % ties\r\n    else\r\n        t = abs(f - 0.5) &lt;= eps(z);  % ties\r\n    end\r\n    x(t) = ceil(z(t));\r\n    \r\n    switch tie\r\n        case 'even'\r\n           m = (mod(x(t),2) == 1); \r\n        case 'odd'\r\n           m = (mod(x(t),2) == 0);\r\n        case 'plus'\r\n           m = (s(t) &lt; 0);\r\n        case 'minus'\r\n           m = (s(t) &gt; 0);\r\n        case 'zero'\r\n           m = 1;\r\n        case 'nan'\r\n           m = NaN;\r\n        otherwise\r\n           m = 0;\r\n    end\r\n    x(t) = x(t) - m;\r\n\r\n    x = s.*scale(x,-n);\r\n\r\n\r\n<\/pre><h4>parse<a name=\"1df88155-b03f-4b7a-94eb-9dbb572107b8\"><\/a><\/h4><p>This parser handles the name-value pairs in a very simplistic manner. A <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/inputparser.addparameter.html\">more serious parser<\/a> would be more discriminating.<\/p><pre class=\"codeinput\">    disp(code(4))\r\n<\/pre><pre class=\"codeoutput\"> \r\n    function [x,n,sig,tie] = parse(varargin)\r\n        x = varargin{1};\r\n        n = 0;\r\n        sig = false;\r\n        tie = 'from';\r\n        for k = 2:nargin\r\n            vk =  varargin{k};\r\n            if isnumeric(vk)\r\n                n = vk;\r\n            elseif vk == \"significant\"\r\n                sig = true;\r\n            elseif vk == \"decimals\" || ...\r\n                vk == \"roundTies\" || ...\r\n                vk == \"digits\"\r\n                % ignore\r\n            else\r\n                tie = char(vk);\r\n                caps = find(double(tie) &lt; double('a'));\r\n                if length(caps) &gt; 1 &amp;&amp; caps(2) &gt; caps(1)+2\r\n                    tie = lower(tie(caps(1):caps(2)-1));\r\n                elseif length(caps) &gt; 0 &amp;&amp; length(tie(caps:end)) &lt;= 5\r\n                    tie = lower(tie(caps(1):end));\r\n                else\r\n                    error(vk + \" not recognized.\")\r\n                end\r\n            end\r\n        end\r\n    end \r\n\r\n<\/pre><h4>scale<a name=\"4fa30978-6e77-41e1-a2a3-b2815a7affa9\"><\/a><\/h4><p>This scaling function always multiplies or divides by positive integer powers of 10, which are exact for <tt>n &lt;= 16<\/tt>.<\/p><pre class=\"codeinput\">    disp(code(5))\r\n<\/pre><pre class=\"codeoutput\">\r\n    function x = scale(x,n)\r\n        k = (n &gt; 0);\r\n        x(k) = x(k).*10.^n(k);\r\n        k = (n &lt; 0);\r\n        x(k) = x(k).\/10.^(-n(k));\r\n    end\r\n\r\n<\/pre><h4>graphic<a name=\"bb4d8214-7f22-4336-87f2-eff7f3e584af\"><\/a><\/h4><p>Here is the graphic from previous posts, now labeled by the <tt>paramValues<\/tt>.<\/p><pre class=\"codeinput\">    graphic\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/round_proto_blog_01.png\" alt=\"\"> <h4>software<a name=\"f03a7fa1-940f-45af-8382-5fff27dc0f36\"><\/a><\/h4><p>The prototype code is available here: <a href=\"https:\/\/blogs.mathworks.com\/cleve\/files\/Round-1.m\">Round.m<\/a><\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_651b77f6f85f406ba6297b9de81009b4() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='651b77f6f85f406ba6297b9de81009b4 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 651b77f6f85f406ba6297b9de81009b4';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2021 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_651b77f6f85f406ba6297b9de81009b4()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2021b<br><\/p><\/div><!--\r\n651b77f6f85f406ba6297b9de81009b4 ##### SOURCE BEGIN #####\r\n%% Round, With Tie Breakers, A Prototype\r\n% In February and March I published three blog posts about\r\n% an enhancement request for MATLAB concerning tie breakers with the\r\n% |round| function, including the ability to round ties to even.\r\n% <https:\/\/blogs.mathworks.com\/cleve\/2021\/02\/25\/round-with-ties-to-even\/\r\n% Round One>,\r\n% <https:\/\/blogs.mathworks.com\/cleve\/2021\/03\/02\/round-with-tie-breakers-round-two\/\r\n% Round Two> and\r\n% <https:\/\/blogs.mathworks.com\/cleve\/2021\/03\/08\/round-with-tie-breakers-round-three\/\r\n% Round Three>.  Since then, a group of us at MathWorks, organized by my\r\n% colleague (and academic great-great-grand-descendant) Heiko Weichelt,\r\n% have been considering the request.  We had a virtual design \r\n% review recently.  This post describes a prototype incorporating the \r\n% features that were discussed at that review.\r\n%\r\n%% round\r\n% Traditionally, |help round| had only one line.\r\n%\r\n%    ROUND(X) rounds each element of X to the nearest integer.\r\n%\r\n% A few years ago, two optional arguments were added.\r\n%\r\n%    ROUND(X, N), for positive integers N, rounds to N digits to the right\r\n%    of the decimal point. If N is zero, X is rounded to the nearest integer.\r\n%    If N is less than zero, X is rounded to the left of the decimal point.\r\n%    N must be a scalar integer.\r\n%\r\n%    ROUND(X, N, 'significant') rounds each element to its N most significant\r\n%    digits, counting from the most-significant or left side of the number. \r\n%    N must be a positive integer scalar.\r\n\r\n%% floor and ceil\r\n% The functions |floor| and |ceil| have important roles in any discussion\r\n% of rounding.  Every real number, |x|, that is not an integer,\r\n% lies between two integers,\r\n%\r\n%    floor(x) < x < ceil(x) = floor(x) + 1\r\n%\r\n% If |x| is an integer, then\r\n%\r\n%    floor(x) = x = ceil(x)\r\n%\r\n% The function |floor(x)| defines \"rounding |x|\r\n% towards minus infinity\" and the function |ceil(x)| is\r\n% \"rounding |x| towards plus infinity\".\r\n\r\n%%\r\n% The function |fix(x)|, which is also known as \"integer part of |x|\", is\r\n% \r\n%    fix(x) = floor(x) if x >= 0,\r\n%           = ceil(x) if x < 0.\r\n%\r\n% The \"fractional part of |x|\" is \r\n% \r\n%    frac(x) = x - fix(x).\r\n\r\n%%\r\n% Two examples\r\n%\r\n%    x = 9.64             x = -9.64 \r\n%    floor(x) = 9         floor(x) = -10\r\n%    ceil(x) = 10         ceil(x) = -9 \r\n%    fix(x) = 9           fix(x) = -9\r\n%    frac(x) = 0.64       frac(x) = -0.64\r\n\r\n%% Ties\r\n% The traditional code for |round(x)| is one line.\r\n%\r\n%    round(x) = sign(x).*floor(abs(x) + 0.5)\r\n%\r\n% This implies that\r\n%    \r\n%    round(x) = floor(x) if frac(x) < 0.5\r\n%             = ceil(x) if frac(x) > 0.5\r\n%\r\n% This unambiguously defines |round(x)| for almost all |x|.\r\n% The only ambiguous situations are the _rounding ties_.\r\n% They occur when the fractional part of |x| is exactly 1\/2,\r\n% or 0.5 in decimal.  Ties are relatively rare.\r\n% Traditionally, MATLAB has rounded ties away from zero.\r\n\r\n%%\r\n% When there is no scaling specified, the ties are the numbers exactly\r\n% halfway between two consecutive integers,\r\n%\r\n%    halfs = -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, ...\r\n%\r\n% The \"round ties away from zero\" rule produces\r\n%\r\n%    round(halfs) = -4, -3, -2, -1, 1, 2, 3, 4, ...\r\n%\r\n\r\n%%\r\n% Recently, there has been some interest in alternatives to\r\n% this behavior.  One alternative is \"round ties to nearest even\".\r\n% For the halfway numbers, this would be\r\n%\r\n%    halfs_even = -4, -2, -2, 0, 0, 2, 2, 4, ...\r\n\r\n%% Nearest decimal\r\n% Here are four examples of rounding to the nearest decimal value.\r\n    format short\r\n    format compact\r\n%%\r\n% * Express intercity mileage distance in whole numbers.  The distance\r\n% from my home office to MathWorks headquarters is 406.3 miles.\r\n% What is this to the nearest mile?\r\n    miles = Round(406.3)\r\n%%\r\n% * The patient's body temperature is 98.64 degrees.  \r\n% Express this in nearest tenths of a degree.\r\n    temp = Round(98.64,1)\r\n%%\r\n% * Express monetary values in hundredths.  The computed interest is\r\n% 13.8327 Euros.  Express this in hundredths of a Euro.\r\n    cents = Round(13.8327,2)\r\n%%\r\n% * The population of Tallahassee in 2019 was reported to be 194,500.\r\n% What is this to the nearest one-thousand people?\r\n    pop = Round(194500,-3)\r\n\r\n%%\r\n% Only one of these examples involves a tie.  With a round-ties-to-even\r\n% rule, the population of Tallahassee would be listed as 194,000 instead\r\n% of 195,000.\r\n\r\n%% IEEE 754\r\n% The |round| function is not the same as the round-to-even setting for\r\n% IEEE 754 floating point arithmetic.  The |round| function is done with\r\n% software by MATLAB; its input is doubles (or singles) and the output is\r\n% flints (floating point numbers whose values are integers.)\r\n% The IEEE 754 setting is done in hardware, its input is extended\r\n% precision or registers with guard bits and its output is doubles that\r\n% are rarely flints.\r\n\r\n%% Name-value pairs\r\n% Several reviewers preferred name-value pairs.  Name-value pairs have been\r\n% part of MATLAB syntax for a long time and a recent enhancement involves\r\n% the use of an equals sign to specify them. For example\r\n%\r\n%    plot(x,y,'ko','markersize',10)\r\n%\r\n% can now be written\r\n%\r\n%    plot(x,y,marker='o',color='black',markersize=10)\r\n\r\n%%\r\n% The left hand portion of a name-value pair is the |paramName| and the\r\n% list of possible right hand portions is |paramValues|.\r\n\r\n%%\r\n% At first, I was not enthusiastic about using a name-value pair for\r\n% tie-braking in |round|.  But after working on this prototype and blog\r\n% post, I am now in favor.  The |paramName| could be\r\n% \r\n%     roundTies\r\n%\r\n% There would be six possible |paramValues|.\r\n%\r\n%     awayFromZero\r\n%     towardZero\r\n%     toEven\r\n%     toOdd\r\n%     towardPlusInfinity\r\n%     towardMinusInfinity\r\n\r\n%%\r\n% For example\r\n\r\n    x = (0.1:0.2:0.9)'\r\n    r_from = Round(x,roundTies='awayFromZero')\r\n    r_even = Round(x,roundTies='toEven')\r\n\r\n%% Not-a-Number\r\n% This occurred to me while writing this post.\r\n% How about a seventh choice for handling ties?\r\n\r\n    r_nan = Round(x,roundTies='toNaN')\r\n\r\n%% help\r\n% The next five sections are the code for a prototype.\r\n% The file name is |Round.m| with a capital |R| so we can also access \r\n% the |round| function from the current release.\r\n% The code is available here: \r\n% <https:\/\/blogs.mathworks.com\/cleve\/files\/Round-1.m Round.m>\r\n%\r\n\r\n    code = split(string(fileread('Round.m')),'%_');\r\n\r\n%%\r\n% The help text is concise.\r\n\r\n    disp(code(1))\r\n\r\n%% examples\r\n% The help text continues with a few examples.\r\n\r\n    disp(code(2))\r\n\r\n%% main\r\n% Here is the body of |Round|.  The numerically sensitive portions are\r\n% the definition of |exact| and the choice of |<| or |<=| in the\r\n% determination of |t|, the ties.\r\n\r\n    disp(code(3))\r\n\r\n%% parse\r\n% This parser handles the name-value pairs in a very simplistic manner.\r\n% A <https:\/\/www.mathworks.com\/help\/matlab\/ref\/inputparser.addparameter.html\r\n% more serious parser> would be more discriminating.\r\n\r\n    disp(code(4))\r\n\r\n%% scale\r\n% This scaling function always multiplies or divides by\r\n% positive integer powers of 10, which are exact for |n <= 16|.\r\n\r\n    disp(code(5))\r\n\r\n%% graphic\r\n% Here is the graphic from previous posts, \r\n% now labeled by the |paramValues|.\r\n\r\n    graphic\r\n\r\n%% software\r\n% The prototype code is available here: \r\n% <https:\/\/blogs.mathworks.com\/cleve\/files\/Round-1.m Round.m>\r\n\r\n##### SOURCE END ##### 651b77f6f85f406ba6297b9de81009b4\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/round_proto_blog_01.png\" onError=\"this.style.display ='none';\" \/><\/div><!--introduction--><p>In February and March I published three blog posts about an enhancement request for MATLAB concerning tie breakers with the <tt>round<\/tt> function, including the ability to round ties to even. <a href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/02\/25\/round-with-ties-to-even\/\">Round One<\/a>, <a href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/03\/02\/round-with-tie-breakers-round-two\/\">Round Two<\/a> and <a href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/03\/08\/round-with-tie-breakers-round-three\/\">Round Three<\/a>.  Since then, a group of us at MathWorks, organized by my colleague (and academic great-great-grand-descendant) Heiko Weichelt, have been considering the request.  We had a virtual design review recently.  This post describes a prototype incorporating the features that were discussed at that review.... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/07\/25\/round-with-tie-breakers-a-prototype\/\">read more >><\/a><\/p>","protected":false},"author":78,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,16,7],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/7241"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/users\/78"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/comments?post=7241"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/7241\/revisions"}],"predecessor-version":[{"id":7244,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/7241\/revisions\/7244"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/media?parent=7241"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/categories?post=7241"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/tags?post=7241"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}