<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Round function issue on large number in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/700152#M214255</link>
    <description>&lt;P&gt;Thank you again&amp;nbsp;&lt;span class="lia-unicode-emoji" title=":grinning_face_with_big_eyes:"&gt;😃&lt;/span&gt;&lt;/P&gt;</description>
    <pubDate>Thu, 19 Nov 2020 10:19:34 GMT</pubDate>
    <dc:creator>SHFBD</dc:creator>
    <dc:date>2020-11-19T10:19:34Z</dc:date>
    <item>
      <title>Round function issue on large number</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/699794#M214079</link>
      <description>&lt;P&gt;I have an odd exprience when rounding a number.&amp;nbsp;&lt;/P&gt;&lt;P&gt;One number is rounded down and the other up:&lt;/P&gt;&lt;PRE&gt;data rounding;
   d1=round(201578736.46500, .01);
   d2=round(276578736.46500, .01);
run;
proc print data=rounding noobs;
run;&lt;/PRE&gt;&lt;P&gt;The first one rounds to .47 and the other one to .46&lt;/P&gt;&lt;P&gt;Are there some kind of limit on the input to round()?&lt;/P&gt;</description>
      <pubDate>Wed, 18 Nov 2020 13:52:27 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/699794#M214079</guid>
      <dc:creator>SHFBD</dc:creator>
      <dc:date>2020-11-18T13:52:27Z</dc:date>
    </item>
    <item>
      <title>Re: Round function issue on large number</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/699798#M214081</link>
      <description>&lt;P&gt;Most numbers that are not integers cannot be represented exactly in digital computers. This is called "&lt;A href="https://en.wikipedia.org/wiki/Machine_epsilon" target="_self"&gt;machine precision&lt;/A&gt;". The numbers can be represented only to within ± a small value epsilon. So the problem isn't the ROUND() function, the problem is a systematic problem that all computers have.&lt;/P&gt;</description>
      <pubDate>Wed, 18 Nov 2020 14:07:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/699798#M214081</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2020-11-18T14:07:35Z</dc:date>
    </item>
    <item>
      <title>Re: Round function issue on large number</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/699973#M214155</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/357620"&gt;@SHFBD&lt;/a&gt;&amp;nbsp;and welcome to the SAS Support Communities!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As&amp;nbsp;&lt;A href="https://communities.sas.com/t5/user/viewprofilepage/user-id/10892" target="_blank" rel="noopener"&gt;PaigeMiller&lt;/A&gt;&amp;nbsp;has mentioned, this has to do with the unavoidable loss of precision that typically occurs when &lt;EM&gt;decimal&lt;/EM&gt; fractions are stored as &lt;EM&gt;binary&lt;/EM&gt; representations.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Let's take a look at how SAS stores these two numbers,&amp;nbsp;201578736.46500 and&amp;nbsp;276578736.46500, in a numeric variable of length 8 (bytes) under Windows or Unix.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The decimal number 201578736.465, converted to the binary system (and with some line breaks inserted), looks like this:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;1100000000111101100011110000.01110111000010100011110
                                10111000010100011110
                                10111000010100011110
                                101110...&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;The 20-binary-digit pattern "&lt;FONT face="courier new,courier"&gt;10111000010100011110&lt;/FONT&gt;" is repeated&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;infinitely many times&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;("periodic fraction").&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The internal 64-bit floating-point representation that SAS under Windows or Unix uses to store the number in an 8-byte numeric variable is based on the above binary representation. However, only 52 of the 64 bits (let alone infinitely many) are available for the binary digits following the first "&lt;FONT face="courier new,courier"&gt;1&lt;/FONT&gt;". The remaining binary digits are rounded (in this particular example: rounded&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;up&lt;/EM&gt;), as can be seen with the BINARY64. format:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;data _null_;
x=201578736.465;
put x binary64.;
run;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Result:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;010000011010&lt;STRONG&gt;100000000111101100011110000011&lt;FONT color="#3366FF"&gt;10111000010100011110&lt;/FONT&gt;11&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;From the mathematical binary representation further above we know that the last two bits,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;FONT face="courier new,courier"&gt;11&lt;/FONT&gt;&lt;/STRONG&gt;, resulted from rounding&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;FONT face="courier new,courier"&gt;1011100001...&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;to&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRONG&gt;11&lt;/STRONG&gt;00000000...&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;Apart from this, the 52 "mantissa bits" (in bold face above) are copied from the periodic binary representation and we recognize the repeating 20-binary-digit pattern (highlighted in blue). If we convert this rounded binary representation back to the decimal system, we obtain&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;201578736.46500000&lt;FONT color="#FF0000"&gt;35762786865234375&lt;/FONT&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;and the (so called) numeric representation error of approx. &lt;FONT face="courier new,courier"&gt;3.576E-9&lt;/FONT&gt; becomes obvious. Given that this number is even slightly larger than&amp;nbsp;201578736.465, we're not surprised that the ROUND function (with a rounding unit of 0.01) rounds it correctly to&amp;nbsp;201578736.47.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now we do the same investigation with 276578736.465:&lt;/P&gt;
&lt;P&gt;The mathematical conversion to the binary system results in:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;10000011111000100000110110000.01110111000010100011110
                                 10111000010100011110
                                 10111000010100011110
                                 101110...&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;The fractional part is, of course, identical to that of the first number because it represents the decimal fraction of 0.465 in both cases. Only the integer part has changed. Note that it has become longer! Since we have crossed a power of 2, namely 2**28 = 268435456, we now have 29 rather than 28 binary digits on the left of the point. As a consequence, the rounding for the internal representation occurs at a different digit! Indeed, the mantissa is now rounded&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;down&lt;/EM&gt;, as can be seen again with the BINARY64. format:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;data _null_;
x=276578736.465;
put x binary64.;
run;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Result:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;010000011011&lt;STRONG&gt;0000011111000100000110110000011&lt;FONT color="#3366FF"&gt;10111000010100011110&lt;/FONT&gt;1&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Once more thanks to the exact periodic fraction, we know that the last bit,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;FONT face="courier new,courier"&gt;1&lt;/FONT&gt;&lt;/STRONG&gt;, resulted from rounding&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;FONT face="courier new,courier"&gt;1011100001...&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;to&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRONG&gt;1&lt;/STRONG&gt;000000000...&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;If we convert this rounded binary representation back to the decimal system, we obtain&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;276578736.4649999&lt;FONT color="#FF0000"&gt;73773956298828125&lt;/FONT&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;and the representation error of approx. &lt;FONT face="courier new,courier"&gt;-2.623E-&lt;STRONG&gt;8&lt;/STRONG&gt;&lt;/FONT&gt; becomes obvious. Given that this number is slightly &lt;EM&gt;less&lt;/EM&gt; than&amp;nbsp;276578736.465, it seems now plausible that it is rounded &lt;EM&gt;down&lt;/EM&gt; to&amp;nbsp;276578736.4&lt;STRONG&gt;6&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For a full explanation, however, we would need to know the internal workings of the ROUND function. Suffice it to say that the ROUND function performs some "&lt;SPAN&gt;extra computations, called fuzzing, to try to make the result agree with decimal arithmetic in the most common situations" (&lt;/SPAN&gt;&lt;A href="https://documentation.sas.com/?cdcId=pgmsascdc&amp;amp;cdcVersion=9.4_3.5&amp;amp;docsetId=lefunctionsref&amp;amp;docsetTarget=p0tj6cmga7p8qln1ejh6ebevm0c9.htm&amp;amp;locale=en#p0zr4tmk27unjwn1izg4801h5l46" target="_blank" rel="noopener"&gt;documentation&lt;/A&gt;; see also the &lt;A href="https://documentation.sas.com/?cdcId=pgmsascdc&amp;amp;cdcVersion=9.4_3.5&amp;amp;docsetId=lefunctionsref&amp;amp;docsetTarget=p1u0w0omad7fyxn1unu83odr6vy2.htm&amp;amp;locale=en" target="_blank" rel="noopener"&gt;ROUNDZ function&lt;/A&gt;, which "&lt;SPAN&gt;does not fuzz the result"&lt;/SPAN&gt;). Apparently, for the second number the amount of fuzzing applied by the ROUND function does not suffice to compensate for the numeric representation error &lt;FONT face="courier new,courier"&gt;-2.623E-8&lt;/FONT&gt;, which is much larger (EDIT: &lt;EM&gt;in absolute value&lt;/EM&gt;) than it would be for a number with a magnitude in the thousands or so. I would not expect such incorrect rounding to occur for much smaller numbers like 1234.465.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For more details and strategies for handling this issue (such as "defining your own rounding routine") please see&amp;nbsp;&lt;A href="http://support.sas.com/resources/papers/dealing-with-numeric-representation-error-in-sas-applications.pdf" target="_blank" rel="noopener"&gt;http://support.sas.com/resources/papers/dealing-with-numeric-representation-error-in-sas-applications.pdf&lt;/A&gt;&amp;nbsp;(in particular p. 11 ff.).&lt;/P&gt;</description>
      <pubDate>Wed, 18 Nov 2020 20:16:00 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/699973#M214155</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2020-11-18T20:16:00Z</dc:date>
    </item>
    <item>
      <title>Re: Round function issue on large number</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/700113#M214232</link>
      <description>&lt;P&gt;Thank you for a very&amp;nbsp;comprehensive&amp;nbsp;&amp;nbsp;answer.&lt;/P&gt;&lt;P&gt;Maybe I just have to accept this loss of precision, but then I would expect it to be the same for all roundings on&amp;nbsp;276578736.46500, right? But if I use input(276578736.46500, 15.2) it rounds to .47, aswell as if I use "format=15.2" in PROC SQL?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;data rounding;&lt;BR /&gt;   d1=round(201578736.46500, .01); /*28 bit integer*/&lt;BR /&gt;   d2=round(276578736.46500, .01); /*29 bit integer*/&lt;BR /&gt;   d3=round(971578736.46500, .01); /*30 bit integer*/&lt;BR /&gt;   d4=input(276578736.46500, 15.2);&lt;BR /&gt;run;&lt;BR /&gt;proc print data=rounding noobs;&lt;BR /&gt;run;&lt;/PRE&gt;</description>
      <pubDate>Thu, 19 Nov 2020 06:37:52 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/700113#M214232</guid>
      <dc:creator>SHFBD</dc:creator>
      <dc:date>2020-11-19T06:37:52Z</dc:date>
    </item>
    <item>
      <title>Re: Round function issue on large number</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/700147#M214251</link>
      <description>&lt;P&gt;You're welcome.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/357620"&gt;@SHFBD&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;Thank you for a very&amp;nbsp;comprehensive&amp;nbsp;&amp;nbsp;answer.&lt;/P&gt;
&lt;P&gt;Maybe I just have to accept this loss of precision, but then I would expect it to be the same for all roundings on&amp;nbsp;276578736.46500, right? But if I use input(276578736.46500, 15.2) it rounds to .47, aswell as if I use "format=15.2" in PROC SQL?&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;No, that's not how SAS does it. The ROUND function uses a different (I think: more sophisticated) algorithm than a mere numeric format.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your example using the INPUT function actually involves an automatic numeric-to-character conversion (see note in the log), which is done using the BEST12. format. So, the relevant intermediate result is that of&lt;/P&gt;
&lt;PRE&gt;put(276578736.46500, best12.)&lt;/PRE&gt;
&lt;P&gt;which is the character string &lt;FONT face="courier new,courier"&gt;'276578736.47'&lt;/FONT&gt;&amp;nbsp;(rounded up, correctly, but not matching the result of the ROUND function). Then the decimal specification ".2" of the informat 15.2 is &lt;EM&gt;ignored&lt;/EM&gt; because the string contains a decimal point. Applying the &lt;EM&gt;format&lt;/EM&gt; 15.2 is a different case, but the result for this particular number is the same as with BEST12. (except for three leading blanks).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I think you obtain results which are more consistent with the internal binary representation if you switch the &lt;A href="https://documentation.sas.com/?cdcId=pgmsascdc&amp;amp;cdcVersion=9.4_3.5&amp;amp;docsetId=lesysoptsref&amp;amp;docsetTarget=n130tap9xs8q36n14gq23sci5y52.htm&amp;amp;locale=en" target="_blank" rel="noopener"&gt;DECIMALCONV= system option&lt;/A&gt;&amp;nbsp;from COMPATIBLE (the default) to STDIEEE:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options decimalconv=stdieee;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Now both the BEST12. and the 15.2 format round&amp;nbsp;&lt;FONT face="courier new,courier"&gt;276578736.465&lt;/FONT&gt;&amp;nbsp;&lt;EM&gt;down&lt;/EM&gt; to&amp;nbsp;&lt;FONT face="courier new,courier"&gt;276578736.46&lt;/FONT&gt;&amp;nbsp;as does the ROUND function for the reason I explained earlier.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The result in variable &lt;FONT face="courier new,courier"&gt;d3&lt;/FONT&gt; can be explained in the same way as in the other two examples. The internal binary floating-point representation of 971578736.46500 (under Windows), converted back to the decimal system is the number&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;971578736.46500003337860107421875&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;and the ROUND function (with rounding unit 0.01) rounds it up.&lt;/P&gt;</description>
      <pubDate>Thu, 19 Nov 2020 09:47:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/700147#M214251</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2020-11-19T09:47:34Z</dc:date>
    </item>
    <item>
      <title>Re: Round function issue on large number</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/700152#M214255</link>
      <description>&lt;P&gt;Thank you again&amp;nbsp;&lt;span class="lia-unicode-emoji" title=":grinning_face_with_big_eyes:"&gt;😃&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 19 Nov 2020 10:19:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Round-function-issue-on-large-number/m-p/700152#M214255</guid>
      <dc:creator>SHFBD</dc:creator>
      <dc:date>2020-11-19T10:19:34Z</dc:date>
    </item>
  </channel>
</rss>

