<?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 Unexpected flagging when doing simple calculation in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Unexpected-flagging-when-doing-simple-calculation/m-p/887098#M350517</link>
    <description>&lt;P&gt;Hi Guys,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I’ve created some stand-alone code in a test file to illustrate some unexpected behavior that I am getting. We have 2 values, ‘a’ and ‘b’, with the ‘b’ column equal to the value of a-0.0001&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I then create a flag to compare the column b with a calculation of a-0.0001 and flag as LT, EQ or GT b. Here is the stand-alone test data and code:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data test;&lt;BR /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; input a b;&lt;BR /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; datalines;&lt;BR /&gt;10.0002 10.0001&lt;BR /&gt;9.9999 9.9998&lt;BR /&gt;9.8747 9.8746&lt;BR /&gt;8.8747 8.8746&lt;BR /&gt;7.8747 7.8746&lt;BR /&gt;6.8747 6.8746&lt;BR /&gt;5.8747 5.8746&lt;BR /&gt;4.8747 4.8746&lt;BR /&gt;3.8747 3.8746&lt;BR /&gt;2.8747 2.8746&lt;BR /&gt;1.8747 1.8746&lt;BR /&gt;0.8747 0.8746&lt;BR /&gt;;&lt;BR /&gt;run;&lt;BR /&gt;&lt;BR /&gt;data test;&lt;BR /&gt;set test;&lt;BR /&gt;a_minus_0001=a-0.0001;&lt;BR /&gt;if b lt a-0.0001 then b_vs_a_minus_0001='LT';&lt;BR /&gt;else if b eq a-0.0001 then b_vs_a_minus_0001='EQ';&lt;BR /&gt;else if b gt a-0.0001 then b_vs_a_minus_0001='GT';&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The result is quite strange/terrifying. As you can see, all results should flag as EQ, but some flag as GT and others flag as LT:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShaneConnolly_0-1690810972755.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/86258i75BF2EC220F3F5C0/image-size/medium?v=v2&amp;amp;px=400" role="button" title="ShaneConnolly_0-1690810972755.png" alt="ShaneConnolly_0-1690810972755.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If anyone could have a little look at this and see if they can add any info. We get the correct results if we force a round to 4 decimal places, but that would not be something that you would intuitively so. I'm stumped with this functionality…&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any help gratefully appreciated.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you.&lt;/P&gt;</description>
    <pubDate>Mon, 31 Jul 2023 13:45:51 GMT</pubDate>
    <dc:creator>ShaneConnolly</dc:creator>
    <dc:date>2023-07-31T13:45:51Z</dc:date>
    <item>
      <title>Unexpected flagging when doing simple calculation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Unexpected-flagging-when-doing-simple-calculation/m-p/887098#M350517</link>
      <description>&lt;P&gt;Hi Guys,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I’ve created some stand-alone code in a test file to illustrate some unexpected behavior that I am getting. We have 2 values, ‘a’ and ‘b’, with the ‘b’ column equal to the value of a-0.0001&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I then create a flag to compare the column b with a calculation of a-0.0001 and flag as LT, EQ or GT b. Here is the stand-alone test data and code:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data test;&lt;BR /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; input a b;&lt;BR /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; datalines;&lt;BR /&gt;10.0002 10.0001&lt;BR /&gt;9.9999 9.9998&lt;BR /&gt;9.8747 9.8746&lt;BR /&gt;8.8747 8.8746&lt;BR /&gt;7.8747 7.8746&lt;BR /&gt;6.8747 6.8746&lt;BR /&gt;5.8747 5.8746&lt;BR /&gt;4.8747 4.8746&lt;BR /&gt;3.8747 3.8746&lt;BR /&gt;2.8747 2.8746&lt;BR /&gt;1.8747 1.8746&lt;BR /&gt;0.8747 0.8746&lt;BR /&gt;;&lt;BR /&gt;run;&lt;BR /&gt;&lt;BR /&gt;data test;&lt;BR /&gt;set test;&lt;BR /&gt;a_minus_0001=a-0.0001;&lt;BR /&gt;if b lt a-0.0001 then b_vs_a_minus_0001='LT';&lt;BR /&gt;else if b eq a-0.0001 then b_vs_a_minus_0001='EQ';&lt;BR /&gt;else if b gt a-0.0001 then b_vs_a_minus_0001='GT';&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The result is quite strange/terrifying. As you can see, all results should flag as EQ, but some flag as GT and others flag as LT:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShaneConnolly_0-1690810972755.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/86258i75BF2EC220F3F5C0/image-size/medium?v=v2&amp;amp;px=400" role="button" title="ShaneConnolly_0-1690810972755.png" alt="ShaneConnolly_0-1690810972755.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If anyone could have a little look at this and see if they can add any info. We get the correct results if we force a round to 4 decimal places, but that would not be something that you would intuitively so. I'm stumped with this functionality…&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any help gratefully appreciated.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you.&lt;/P&gt;</description>
      <pubDate>Mon, 31 Jul 2023 13:45:51 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Unexpected-flagging-when-doing-simple-calculation/m-p/887098#M350517</guid>
      <dc:creator>ShaneConnolly</dc:creator>
      <dc:date>2023-07-31T13:45:51Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected flagging when doing simple calculation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Unexpected-flagging-when-doing-simple-calculation/m-p/887101#M350519</link>
      <description>&lt;P&gt;Digital computers cannnot represent most decimal numbers exactly. So that's why you get the result you see. If, however, you use the &lt;A href="https://documentation.sas.com/doc/en/pgmmvacdc/9.4/lefunctionsref/p18pa7u3zufu9nn1ivv67uknw3i7.htm" target="_self"&gt;FUZZ function&lt;/A&gt;, the results should make sense. The ROUND function can work here as well.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data test1;
set test;
if fuzz(b-(a-0.0001)) &amp;lt; 0 then b_vs_a_minus_0001='LT';
else if fuzz(b-(a-0.0001)) = 0 then b_vs_a_minus_0001='EQ';
else if fuzz(b-(a-0.0001)) &amp;gt; 0 then b_vs_a_minus_0001='GT';
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;See here for a more detailed discussion of the matter:&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://communities.sas.com/t5/SAS-Programming/comparing-two-values/m-p/761113#M240787" target="_blank" rel="noopener"&gt;Machine Precision&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://communities.sas.com/t5/SAS-Programming/Formula-evaluates-totals-the-same-set-of-variables-differently/m-p/761364#M240925" target="_blank" rel="noopener"&gt;Machine Precision part 2&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Mon, 31 Jul 2023 13:57:03 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Unexpected-flagging-when-doing-simple-calculation/m-p/887101#M350519</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2023-07-31T13:57:03Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected flagging when doing simple calculation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Unexpected-flagging-when-doing-simple-calculation/m-p/887181#M350534</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/446360"&gt;@ShaneConnolly&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;You have already got a correct solution. Let me just add a few bits (i.e., binary digits) ...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I like your example values with the .8747 decimals because they demonstrate that not only the decimals are relevant for the computer's result of the subtraction, but also the &lt;EM&gt;order of magnitude&lt;/EM&gt; of the numbers in the &lt;EM&gt;binary system&lt;/EM&gt;. For instance, 2.8747 and 3.8747 fall into the (right-open) interval [2**1, 2**2) and hence are of the same order of magnitude in the binary system.&amp;nbsp; However, 4.8747, 5.8747,&amp;nbsp;6.8747 and&amp;nbsp;7.8747 belong to the next higher order of magnitude: [2**2, 2**3). Finally, 8.8747 and 9.8747 share yet another order of magnitude: [2**3, 2**4). This is the reason why the flag values (in variable&amp;nbsp;&lt;SPAN&gt;&lt;FONT face="courier new,courier"&gt;b_vs_a_minus_0001&lt;/FONT&gt;) are the same &lt;EM&gt;within&lt;/EM&gt; each of these three groups, but possibly differ &lt;EM&gt;between&lt;/EM&gt; the groups.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;EM&gt;All&lt;/EM&gt;&amp;nbsp;of the numbers in your code are among those mentioned by Paige Miller that are not exactly representable in the computer's memory (here: in the 64 bits of a numeric SAS variable of length 8 bytes) because they are &lt;EM&gt;periodic fractions&lt;/EM&gt; in the binary system. This is true for 99.84% (!) of the numbers with up to four decimal places, hence no surprise here.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;(The repeating digit patterns of those periodic fractions have a length of &lt;EM&gt;500&lt;/EM&gt;&amp;nbsp;bits in each of your examples, so you cannot recognize the repetition when looking at only 64 bits.)&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;The problem starts when the binary numbers are rounded to &lt;EM&gt;53 bits&lt;/EM&gt;&amp;nbsp;(52 mantissa bits plus the so called "implied bit") to fit into the 8 bytes (=64 bits), 12 bits of which are reserved for the sign and the exponent (corresponding to the order of magnitude; assuming a Windows or Unix operating system), see&amp;nbsp;&lt;A href="https://documentation.sas.com/doc/en/lrcon/9.4/p0ji1unv6thm0dn1gp4t01a1u0g6.htm" target="_blank" rel="noopener"&gt;Numerical Accuracy in SAS Software&lt;/A&gt;:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt;exact   0.8747:     &lt;STRONG&gt;1&lt;/STRONG&gt;.&lt;STRONG&gt;1011111111011000101011011010101110011111010101&lt;/STRONG&gt;011001101... * 2**-1
rounded 0.8747:     &lt;STRONG&gt;1&lt;/STRONG&gt;.&lt;STRONG&gt;1011111111011000101011011010101110011111010101&lt;/STRONG&gt;0110&lt;FONT color="#FF0000"&gt;&lt;STRONG&gt;10&lt;/STRONG&gt;&lt;/FONT&gt;       * 2**-1 (rounded up)
rounded 1.8747:    &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1&lt;/STRONG&gt;&lt;/FONT&gt;.&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;0110&lt;STRONG&gt;&lt;FONT color="#FF0000"&gt;1&lt;/FONT&gt;&lt;/STRONG&gt;        * 2**0  (rounded up)
rounded 2.8747:   &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1.0&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;0110         * 2**1  (rounded down)
rounded 3.8747:   &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1.1&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;0110         * 2**1  (rounded down)
rounded 4.8747:  &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1.00&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;011          * 2**2  (rounded down)
rounded 5.8747:  &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1.01&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;011          * 2**2  (rounded down)
rounded 6.8747:  &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1.10&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;011          * 2**2  (rounded down)
rounded 7.8747:  &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1.11&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;011          * 2**2  (rounded down)
rounded 8.8747: &lt;FONT color="#3366FF"&gt;&lt;STRONG&gt;1.000&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;11011111111011000101011011010101110011111010101&lt;FONT color="#FF0000"&gt;10&lt;/FONT&gt;&lt;/STRONG&gt;           * 2**3  (rounded up)
rounded 9.8747: &lt;STRONG&gt;&lt;FONT color="#3366FF"&gt;1.001&lt;/FONT&gt;11011111111011000101011011010101110011111010101&lt;/STRONG&gt;&lt;FONT color="#FF0000"&gt;&lt;STRONG&gt;10&lt;/STRONG&gt;&lt;/FONT&gt;           * 2**3  (rounded up)&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;Highlighted in blue are the bits occupied by the integer part of the decimal numbers. As you can see, the place where the rounding occurs depends on the order of magnitude of the number (rounded-up digits are highlighted in red). The rounding error propagates when 0.0001 is subtracted. Finally,&amp;nbsp;the result of the subtraction (done at a greater precision) is rounded and, again, it depends on the order of magnitude of the result, where exactly the rounding occurs.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Here is what the subtraction 9.8747−0.0001 looks like internally:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt; 1.0011101111111101100010101101101010111001111101010110                  * 2**3
&lt;U&gt;-0.000000000000000011010001101101110001011101011000111000100001100101101 * 2**3&lt;/U&gt;
=1.001110111111110010111001001000111010001010011100011111011110011010011 * 2**3
Rounded &lt;STRONG&gt;&lt;EM&gt;up&lt;/EM&gt;&lt;/STRONG&gt; to:
 1.001110111111110010111001001000111010001010011100&lt;STRONG&gt;&lt;FONT color="#FF0000"&gt;1000&lt;/FONT&gt;&lt;/STRONG&gt;                  * 2**3&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;However, the correct representation of 9.8746 is&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT size="4"&gt; 1.001110111111110010111001001000111010001010011100&lt;STRONG&gt;&lt;FONT color="#008000"&gt;0111&lt;/FONT&gt;&lt;/STRONG&gt; * 2**3, rounded &lt;STRONG&gt;&lt;EM&gt;down&lt;/EM&gt;&lt;/STRONG&gt; from
 1.001110111111110010111001001000111010001010011100011101111001101001101... * 2**3&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;which explains the "LT" flag you obtained for this case. &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;The other results can be explained analogously.&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Mon, 31 Jul 2023 20:08:25 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Unexpected-flagging-when-doing-simple-calculation/m-p/887181#M350534</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2023-07-31T20:08:25Z</dc:date>
    </item>
  </channel>
</rss>

