<?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: Rounding to multiples of a value lead to wrnog values, a small delta is added in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961038#M374706</link>
    <description>&lt;P&gt;Let me add something:&lt;BR /&gt;The problem occurs only in the difference and not, if one calculates a single term:&lt;BR /&gt;&lt;BR /&gt;Data work.tst;&lt;BR /&gt;uiva=-0.07918;&lt;BR /&gt;changeLines=round(UIVA,0.02); &lt;BR /&gt;changeLines2=round(UIVA*50)/50;&lt;BR /&gt;if changelines=-0.08 then a='Y'; else a='n';&lt;BR /&gt;if changelines2=-0.08 then a2='Y'; else a2='n';&lt;BR /&gt;diff1=changelines + 0.08;&lt;BR /&gt;diff2=changelines2 + 0.08;&lt;BR /&gt;output;&lt;BR /&gt;run;&lt;/P&gt;
&lt;DIV&gt;
&lt;DIV id="IDX"&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;
&lt;DIV id="IDX"&gt;
&lt;TABLE class="table" aria-label="Data Set WORK.TST1"&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TH class="r header" scope="col"&gt;Obs&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;uiva&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;changeLines&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;changeLines2&lt;/TH&gt;
&lt;TH class="header" scope="col"&gt;a&lt;/TH&gt;
&lt;TH class="header" scope="col"&gt;a2&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;diff1&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;diff2&lt;/TH&gt;
&lt;/TR&gt;
&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TH class="r rowheader" scope="row"&gt;1&lt;/TH&gt;
&lt;TD class="r data"&gt;-0.07918&lt;/TD&gt;
&lt;TD class="r data"&gt;-0.08&lt;/TD&gt;
&lt;TD class="r data"&gt;-0.08&lt;/TD&gt;
&lt;TD class="data"&gt;Y&lt;/TD&gt;
&lt;TD class="data"&gt;Y&lt;/TD&gt;
&lt;TD class="r data"&gt;0&lt;/TD&gt;
&lt;TD class="r data"&gt;0&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;That is quite strange!&amp;nbsp;&lt;/P&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;</description>
    <pubDate>Thu, 06 Mar 2025 08:48:20 GMT</pubDate>
    <dc:creator>Georg</dc:creator>
    <dc:date>2025-03-06T08:48:20Z</dc:date>
    <item>
      <title>Rounding to multiples of a value lead to wrnog values, a small delta is added</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961034#M374702</link>
      <description>&lt;P&gt;I am using SAS 9.4.&lt;BR /&gt;The following code demonstates an error of the round &lt;STRONG&gt;(x, b)&lt;/STRONG&gt; function:&lt;BR /&gt;Data work.tst;&lt;BR /&gt;uiva=-0.07918;&lt;BR /&gt;dciva=0.20066;&lt;BR /&gt;changeLines=( round(DCIVA,0.02) - round(UIVA,0.02))*10; &lt;BR /&gt;changeLines2=( round(DCIVA*50) - round(UIVA*50))/5;&lt;BR /&gt;changeLetters=changeLines*5;&lt;BR /&gt;if changelines=2.8 then a='Y'; else a='n';&lt;BR /&gt;if changelines2=2.8 then a2='Y'; else a2='n';&lt;BR /&gt;diff1=changelines - 2.8;&lt;BR /&gt;diff2=changelines2 - 2.8;&lt;BR /&gt;output;&lt;BR /&gt;run;&lt;BR /&gt;&lt;BR /&gt;proc print data=Work.tst;&lt;BR /&gt;run;&lt;/P&gt;
&lt;DIV&gt;
&lt;DIV id="IDX"&gt;
&lt;TABLE class="table" aria-label="Data Set WORK.TST"&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TH class="r header" scope="col"&gt;Obs&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;uiva&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;dciva&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;changeLines&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;changeLines2&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;changeLetters&lt;/TH&gt;
&lt;TH class="header" scope="col"&gt;a&lt;/TH&gt;
&lt;TH class="header" scope="col"&gt;a2&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;diff1&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;diff2&lt;/TH&gt;
&lt;/TR&gt;
&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TH class="r rowheader" scope="row"&gt;1&lt;/TH&gt;
&lt;TD class="r data"&gt;-0.07918&lt;/TD&gt;
&lt;TD class="r data"&gt;0.20066&lt;/TD&gt;
&lt;TD class="r data"&gt;2.8&lt;/TD&gt;
&lt;TD class="r data"&gt;2.8&lt;/TD&gt;
&lt;TD class="r data"&gt;14&lt;/TD&gt;
&lt;TD class="data"&gt;n&lt;/TD&gt;
&lt;TD class="data"&gt;Y&lt;/TD&gt;
&lt;TD class="r data"&gt;4.4409E-16&lt;/TD&gt;
&lt;TD class="r data"&gt;0&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So rounding by &lt;STRONG&gt;round(x, 0.02)&lt;/STRONG&gt; leads to different result than&lt;STRONG&gt; round(x*50)/50&lt;/STRONG&gt;.&lt;BR /&gt;The difference between both is a small delta=4.44e-16 !!!&lt;BR /&gt;&lt;BR /&gt;This is a bad mistake, as typically it is often not seen when fomatted values are shown.&lt;BR /&gt;But it is effective when you make comparsions (see n for comparison a)&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;Is this bug going to be fixed somehow?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 06 Mar 2025 08:17:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961034#M374702</guid>
      <dc:creator>Georg</dc:creator>
      <dc:date>2025-03-06T08:17:36Z</dc:date>
    </item>
    <item>
      <title>Re: Rounding to multiples of a value lead to wrnog values, a small delta is added</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961036#M374704</link>
      <description>&lt;P&gt;Differences like these are natural because of the way numeric data is stored and calculated. With 8-byte real,&amp;nbsp;&lt;EM&gt;only&lt;/EM&gt;&amp;nbsp;about 15 decimal digits can be processed precisely. And most decimal fractions can not be converted to finite binary numbers anyway.&lt;/P&gt;
&lt;P&gt;You will find the same "bug" in all software running on computers with a limited number of bits.&lt;/P&gt;</description>
      <pubDate>Thu, 06 Mar 2025 08:34:22 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961036#M374704</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2025-03-06T08:34:22Z</dc:date>
    </item>
    <item>
      <title>Re: Rounding to multiples of a value lead to wrnog values, a small delta is added</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961037#M374705</link>
      <description>&lt;P&gt;&lt;SPAN&gt;I think the following document explains your question well.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;A href="https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/lefunctionsref/p0tj6cmga7p8qln1ejh6ebevm0c9.htm" target="_blank"&gt;SAS Help Center: ROUND Function&lt;/A&gt;&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 06 Mar 2025 08:37:58 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961037#M374705</guid>
      <dc:creator>ShenQicheng</dc:creator>
      <dc:date>2025-03-06T08:37:58Z</dc:date>
    </item>
    <item>
      <title>Re: Rounding to multiples of a value lead to wrnog values, a small delta is added</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961038#M374706</link>
      <description>&lt;P&gt;Let me add something:&lt;BR /&gt;The problem occurs only in the difference and not, if one calculates a single term:&lt;BR /&gt;&lt;BR /&gt;Data work.tst;&lt;BR /&gt;uiva=-0.07918;&lt;BR /&gt;changeLines=round(UIVA,0.02); &lt;BR /&gt;changeLines2=round(UIVA*50)/50;&lt;BR /&gt;if changelines=-0.08 then a='Y'; else a='n';&lt;BR /&gt;if changelines2=-0.08 then a2='Y'; else a2='n';&lt;BR /&gt;diff1=changelines + 0.08;&lt;BR /&gt;diff2=changelines2 + 0.08;&lt;BR /&gt;output;&lt;BR /&gt;run;&lt;/P&gt;
&lt;DIV&gt;
&lt;DIV id="IDX"&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;
&lt;DIV id="IDX"&gt;
&lt;TABLE class="table" aria-label="Data Set WORK.TST1"&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TH class="r header" scope="col"&gt;Obs&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;uiva&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;changeLines&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;changeLines2&lt;/TH&gt;
&lt;TH class="header" scope="col"&gt;a&lt;/TH&gt;
&lt;TH class="header" scope="col"&gt;a2&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;diff1&lt;/TH&gt;
&lt;TH class="r header" scope="col"&gt;diff2&lt;/TH&gt;
&lt;/TR&gt;
&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TH class="r rowheader" scope="row"&gt;1&lt;/TH&gt;
&lt;TD class="r data"&gt;-0.07918&lt;/TD&gt;
&lt;TD class="r data"&gt;-0.08&lt;/TD&gt;
&lt;TD class="r data"&gt;-0.08&lt;/TD&gt;
&lt;TD class="data"&gt;Y&lt;/TD&gt;
&lt;TD class="data"&gt;Y&lt;/TD&gt;
&lt;TD class="r data"&gt;0&lt;/TD&gt;
&lt;TD class="r data"&gt;0&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;That is quite strange!&amp;nbsp;&lt;/P&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;</description>
      <pubDate>Thu, 06 Mar 2025 08:48:20 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961038#M374706</guid>
      <dc:creator>Georg</dc:creator>
      <dc:date>2025-03-06T08:48:20Z</dc:date>
    </item>
    <item>
      <title>Re: Rounding to multiples of a value lead to wrnog values, a small delta is added</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961042#M374707</link>
      <description>&lt;P&gt;Thank you that makse it clear.&lt;BR /&gt;&lt;BR /&gt;So always comaprind with delta:&amp;nbsp; e.g.&amp;nbsp; &amp;nbsp;x1-x2 &amp;lt; 1e-10&amp;nbsp;&lt;BR /&gt;or maybe via round(x1, a) =round(x2,b)...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 06 Mar 2025 09:40:22 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961042#M374707</guid>
      <dc:creator>Georg</dc:creator>
      <dc:date>2025-03-06T09:40:22Z</dc:date>
    </item>
    <item>
      <title>Re: Rounding to multiples of a value lead to wrnog values, a small delta is added</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961052#M374709</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/35612"&gt;@Georg&lt;/a&gt;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The ROUND function works well. As &lt;A href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562" target="_blank" rel="noopener"&gt;Kurt_Bremser&lt;/A&gt; said already, the issue is about arithmetic calculations with numbers of limited precision (due to numeric representation issues).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;93    data _null_;
94    uiva=-0.07918;
95    dciva=0.20066;
96    if round(DCIVA,0.02)=0.2  then put 'OK 1';
97    if round(UIVA,0.02)=-0.08 then put 'OK 2';
98    if round(DCIVA*50)=10     then put 'OK 3';
99    if round(UIVA*50)=-4      then put 'OK 4';
100   if 0.2-(-0.08)=0.28       then put 'OK 5';
101   if 0.28*10 ne 2.8         then put 'Surprised?';
102   run;

OK 1
OK 2
OK 3
OK 4
OK 5
Surprised?&lt;/PRE&gt;
&lt;P&gt;The first four OKs in the log above are what you would expect. The fifth OK is already a bit lucky because with slightly different numbers the comparison fails:&lt;/P&gt;
&lt;PRE&gt;125   data _null_;
126   if 0.2-(-0.0&lt;STRONG&gt;4&lt;/STRONG&gt;) ne 0.2&lt;STRONG&gt;4&lt;/STRONG&gt; then put 'Surprised again?';
127   run;

Surprised again?&lt;/PRE&gt;
&lt;P&gt;This is due to the internal 64-bit floating-point binary representations of both 0.2 and 0.04 (and also 0.08) being inevitably affected by rounding errors as the exact binary representations of those numbers would require infinitely many binary digits -- which the 64 available bits obviously cannot accommodate. Arithmetic calculations with rounded numbers can easily propagate rounding errors and hence lead to slightly incorrect results. Sometimes, however, two rounding errors cancel out and the result is correct (as in&amp;nbsp;&lt;FONT face="courier new,courier"&gt;0.2-(-0.08)=0.28&lt;/FONT&gt;).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The "surprise" caused by the calculation&amp;nbsp;0.28*10 is just another example of a rounding error -- here contained in the internal representation of 0.28 only -- propagating to the result of a calculation. Let's take a closer look at this example and why it does not yield exactly 2.8.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The decimal number 0.28 written (mathematically) in the binary system is&amp;nbsp;a repeating fraction:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;0.0&lt;FONT color="#00DD00"&gt;&lt;STRONG&gt;1&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color="#00CCFF"&gt;00011110101110000101&lt;/FONT&gt;0001111010111000010100011110101110000101...&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;The 20-digit-pattern highlighted in blue is actually repeated forever (only three blocks of these are shown above). SAS uses the internal binary representation of 0.28 shown below, which can be seen by applying&amp;nbsp;the BINARY64. format to 0.28.&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;&lt;FONT color="#00CCFF"&gt;&lt;FONT color="#999999"&gt;001111111101&lt;/FONT&gt;00011110101110000101&lt;/FONT&gt;&lt;EM&gt;00011110101110000101&lt;/EM&gt;000111101&lt;FONT color="#FF0000"&gt;100&lt;/FONT&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;We recognize two complete copies of the repeating 20-digit-pattern, but the third copy is &lt;EM&gt;rounded&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;(up)&amp;nbsp;&lt;/SPAN&gt;to fit into the 64 bits, more precisely: into the 52&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;mantissa&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;bits plus the implied bit (highlighted in green above).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Multiplying this number by the decimal number 10 (binary: 1010) amounts to summing two shifted copies of it (because of the two 1s in "1010").&lt;/P&gt;
&lt;P&gt;Written mathematically as multiples of 2**-2=0.25:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt; &lt;FONT color="#00DD00"&gt;&lt;STRONG&gt;1&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color="#00CCFF"&gt;000&lt;/FONT&gt;.&lt;FONT color="#00CCFF"&gt;11110101110000101&lt;/FONT&gt;00011110101110000101000111101&lt;FONT color="#FF0000"&gt;100&lt;/FONT&gt;  
+  &lt;FONT color="#00DD00"&gt;&lt;STRONG&gt;1&lt;/STRONG&gt;&lt;FONT color="#00CCFF"&gt;0&lt;/FONT&gt;&lt;/FONT&gt;.&lt;FONT color="#00CCFF"&gt;0011110101110000101&lt;/FONT&gt;00011110101110000101000111101&lt;FONT color="#FF0000"&gt;100&lt;/FONT&gt;
---------------------------------------------------------
&lt;/FONT&gt; &lt;FONT size="4"&gt;1011.001100110011001100110011001100110011001100110011&lt;STRONG&gt;&lt;FONT color="#FF0000"&gt;1&lt;/FONT&gt;&lt;/STRONG&gt;&lt;FONT color="#FFAAAA"&gt;00&lt;/FONT&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Now we see how the rounding error mentioned above affects the summation and leads to a result that is slightly too large. Moreover, it contains 55 binary digits, so it must be rounded again to 52+1=53 bits: The two trailing zeros at the end are cut off, but the rounding error persists in the remaining "&lt;FONT face="courier new,courier"&gt;&lt;STRONG&gt;&lt;FONT color="#FF6600"&gt;1&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;". The correct internal representation of 2.8 has a zero there, rounded down from (the repeating 4-digit pattern)&amp;nbsp;&lt;STRONG&gt;0&lt;/STRONG&gt;011..., as can be seen in the BINARY64. format. The place value of the final incorrect "1" is 2**-51=4.44089...E-16, which is exactly the rounding difference that you found in variable &lt;FONT face="courier new,courier"&gt;diff1&lt;/FONT&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;We can correct the rounding error by using the ROUND function with a suitable rounding unit such as 1E-9 (or anything else in {1E-2, 1E-3, ..., 1E-15}).&lt;/P&gt;
&lt;PRE&gt;186   data _null_;
187   if round(0.28*10,1e-9)=2.8 then put 'OK';
188   run;

OK&lt;/PRE&gt;</description>
      <pubDate>Thu, 06 Mar 2025 11:16:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Rounding-to-multiples-of-a-value-lead-to-wrnog-values-a-small/m-p/961052#M374709</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2025-03-06T11:16:01Z</dc:date>
    </item>
  </channel>
</rss>

