BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
himalayan
Fluorite | Level 6

Hi All,

 

We noticed an issue with our SAS installation recently. We are running Windows 32bit SAS 9.3TS Level 1M0. Calculation on change from baseline were not consistent between the divide function and the divide operator.

 

We replicated the issue with the following code:

 

data _null_;  
   do i=1 to 50;
      base = ranuni(1234)*10;
      aval = ranuni(2345)*10;
      chg1 = divide(aval-base,base)*100;
      chg2 = (aval-base)/base*100;
      if chg1 ne chg2 then do;
         put (base aval chg1 chg2) (=best16.);
         put (chg1 chg2) (=hex16.) /;
         end;
        else put "They are equal!";
      end;
   run;
 
That produced the log below showing that the two results are not consistent. We were able to reproduce this on our 64 bit linux SAS9.3 installation also. Subsequent tests on other environments with SAS 9.4 didn't seem to be an issue.
 
Has anyone seen this issue before and/or know how to handle it so we don't have to go through our entire codebase?
 
Thanks 
 
 
 
 
base=2.43811160439538 aval=0.8947511347452 chg1=-63.301469336672 chg2=-63.301469336672
chg1=C04FA6968C16E063 chg2=C04FA6968C16E062

They are equal!
They are equal!
They are equal!
They are equal!
They are equal!
They are equal!
base=9.67440287101753 aval=7.3735176154289 chg1=-23.783227618953 chg2=-23.783227618953
chg1=C037C8819AF0BA3B chg2=C037C8819AF0BA3A

base=4.02947708220662 aval=3.73164565941861 chg1=-7.3913169553235 chg2=-7.3913169553235
chg1=C01D90B56455F04B chg2=C01D90B56455F048

They are equal!
base=2.83903048971623 aval=3.50611041928926 chg1=23.4967511616866 chg2=23.4967511616866
chg1=40377F2B1589B19C chg2=40377F2B1589B19D

base=2.5577507878457 aval=4.36403616534734 chg1=70.6200692454097 chg2=70.6200692454097
chg1=4051A7AF36EA9290 chg2=4051A7AF36EA9291

base=1.24002424592153 aval=7.1392959762082 chg1=475.738417993801 chg2=475.738417993801
chg1=407DBBD08F62E270 chg2=407DBBD08F62E271

base=0.02762168181484 aval=5.10001865453088 chg1=18363.8237769844 chg2=18363.8237769844
chg1=40D1EEF4B8C319D0 chg2=40D1EEF4B8C319D1

They are equal!
They are equal!
They are equal!
base=6.40857011843872 aval=7.72992366353512 chg1=20.618539247852 chg2=20.618539247852
chg1=40349E589690D118 chg2=40349E589690D117

They are equal!
base=5.34773293200309 aval=4.21025120383606 chg1=-21.270354047785 chg2=-21.270354047785
chg1=C0354535EC419384 chg2=C0354535EC419386

base=4.93211107092542 aval=9.43430182032022 chg1=91.283239259047 chg2=91.283239259047
chg1=4056D220978EA332 chg2=4056D220978EA333

base=7.06284289577177 aval=3.47936205262289 chg1=-50.737088393884 chg2=-50.737088393884
chg1=C0495E58E998FF24 chg2=C0495E58E998FF23

base=1.8100535458932 aval=8.78799389060028 chg1=385.510161317561 chg2=385.510161317561
chg1=407818299EE9E9B5 chg2=407818299EE9E9B6

base=1.39341779583759 aval=3.15914520675277 chg1=126.719166081398 chg2=126.719166081398
chg1=405FAE06D12BFFB4 chg2=405FAE06D12BFFB5

They are equal!
They are equal!
base=5.46229686376746 aval=6.93179405151484 chg1=26.902550783991 chg2=26.902550783991
chg1=403AE70D9174386E chg2=403AE70D9174386C

base=6.02654237115129 aval=2.48575991135359 chg1=-58.753133085851 chg2=-58.753133085851
chg1=C04D6066AA3AA1DB chg2=C04D6066AA3AA1DA

base=3.49072226020076 aval=2.76867309248479 chg1=-20.68480715147 chg2=-20.68480715147
chg1=C034AF4F857FA1A2 chg2=C034AF4F857FA1A1

base=7.28259827349456 aval=9.18937070723128 chg1=26.1825843212653 chg2=26.1825843212653
chg1=403A2EBDD89898BD chg2=403A2EBDD89898BC

base=6.19594010812973 aval=7.12793015741181 chg1=15.0419473561278 chg2=15.0419473561278
chg1=402E157A1FB5720A chg2=402E157A1FB5720B

They are equal!
base=3.37719455518629 aval=3.55450391003606 chg1=5.25019663369642 chg2=5.25019663369643
chg1=401500338BDD2E83 chg2=401500338BDD2E8A

base=5.20533108394841 aval=7.16976712326043 chg1=37.7389258748538 chg2=37.7389258748538
chg1=4042DE951F815526 chg2=4042DE951F815525

base=4.38564417622315 aval=1.62309248075965 chg1=-62.990785035428 chg2=-62.990785035428
chg1=C04F7ED20B4643EF chg2=C04F7ED20B4643F1

base=8.29834726559853 aval=7.32943984089859 chg1=-11.675908391019 chg2=-11.675908391019
chg1=C0275A10AA250A24 chg2=C0275A10AA250A21

base=1.5316278820539 aval=5.23635912930423 chg1=241.881940819875 chg2=241.881940819875
chg1=406E3C38DBF44BEB chg2=406E3C38DBF44BEA

base=3.81391693084218 aval=9.10642663906628 chg1=138.768352960835 chg2=138.768352960835
chg1=4061589658F2D23C chg2=4061589658F2D23B

base=2.74778533854884 aval=5.90477663367278 chg1=114.89220976742 chg2=114.89220976742
chg1=405CB919F6FF0F44 chg2=405CB919F6FF0F45

base=3.05036562171316 aval=3.14132258907953 chg1=2.98183820060527 chg2=2.98183820060527
chg1=4007DACDFC8C8149 chg2=4007DACDFC8C8148

base=2.95707058764858 aval=3.66100074893842 chg1=23.8049833585337 chg2=23.8049833585337
chg1=4037CE1363AEB9F4 chg2=4037CE1363AEB9F6

base=5.61540480964603 aval=9.85869430930293 chg1=75.5651576956279 chg2=75.565157695628
chg1=4052E42B8B2EF37F chg2=4052E42B8B2EF380

base=1.14962568560132 aval=8.88840151433293 chg1=673.156134701686 chg2=673.156134701686
chg1=4085093FC38CEC18 chg2=4085093FC38CEC17

They are equal!
base=7.88632248895537 aval=9.2173436373553 chg1=16.8775896530226 chg2=16.8775896530226
chg1=4030E0A9B72B0A3E chg2=4030E0A9B72B0A3D

They are equal!
base=0.08909457367337 aval=9.41624740577128 chg1=10468.8225640903 chg2=10468.8225640903
chg1=40C4726949C7B571 chg2=40C4726949C7B570

base=9.68923215739859 aval=0.63517195202185 chg1=-93.444558436585 chg2=-93.444558436585
chg1=C0575C73A53A92DB chg2=C0575C73A53A92DA

base=9.73705197672223 aval=8.64485994383919 chg1=-11.216865592318 chg2=-11.216865592318
chg1=C0266F0901C5436A chg2=C0266F0901C5436B

base=1.74953654489924 aval=8.23659310035249 chg1=370.787142135797 chg2=370.787142135797
chg1=40772C98225A28CA chg2=40772C98225A28CB
NOTE: DATA statement used (Total process time):
      real time           0.04 seconds
      cpu time            0.03 seconds

 
1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Running on RedHat Linux I only found differences with SAS version 9.1 (TS1M3) 

No differences using 9.2 (TS2M3), 9.3 (TS1M2), or 9.4 (TS1M5).

Check your maintenance release level.

Also note how long ago these older versions of SAS were released (or better supplanted).

https://blogs.sas.com/content/iml/2013/08/02/how-old-is-your-version-of-sas-release-dates-for-sas-so...

 

 

View solution in original post

14 REPLIES 14
himalayan
Fluorite | Level 6
Thanks Kurt, so far it only seems to be a problem on 9.3. But I couldn't find any hotfixes or mentions of the issue elsewhere
Kurt_Bremser
Super User

The function was introduced in 9.1, so it might be some "immaturity" that was fixed "under the hood" between 9.3 and 9.4.

Like you, I could not find a note in the knowledge base.

s_lassen
Meteorite | Level 14

The differences are rather small, I think the reason they are there is this:

SAS uses 8-byte real numbers. The Intel/AMD numeric processor works with 10-byte real numbers. When you call DIVIDE, the division is performed in 10-byte reals, the result is returned as an 8-byte real, and that is again converted to a 10-byte real before the division with 100. When you it with the divide operator, the whole thing, including the division by 100, is done in 10-byte reals before the result is returned to SAS as an 8-byte number.

 

My guess is therefore that what you get with the divide function call is the same as you would get with

chg2=(aval-base)/base;
chg2=chg2/100;

If you dropped the division by 100, the two values would probably also be the same.

 

If by "other environments" you mean mainframes, they process 8-byte reals in the numeric processor, so there should not be any differences.

himalayan
Fluorite | Level 6

Thanks for the reply s_lassen.

 

I tried testing the proposed scenarios you mentioned with the following, and the issue persists

 

data _null_;  
   do i=1 to 50;
      base = ranuni(1234)*10;
      aval = ranuni(2345)*10;
      chg1 = divide(aval-base,base)*100;
      chg2=(aval-base)/base;
      chg2=chg2*100;
      if chg1 ne chg2 then do;
         put (base aval chg1 chg2) (=best16.);
         put (chg1 chg2) (=hex16.) /;
         end;
        else put "They are equal!";
      end;
   run;

 

Same is true if I drop the multiplication by 100 😞

 

Thanks

 

s_lassen
Meteorite | Level 14

When I submit any of your programs, I get all "equal" messages. I am running on a Windows 64 bits platform, SAS 9.4 TS Level 1M4.

himalayan
Fluorite | Level 6

Thanks for confirming. Can someone with a 9.1-9.3 installation please post their results?

I'm trying to gather some evidence to go back to the SAS Technical Support, but they keep sending me to the same numeric precision documents

 

data_null__
Jade | Level 19

@himalayan wrote:

 but they keep sending me to the same numeric precision documents

 


Because the differences are due to numeric precision as explained in the documents.  Round percent change from baseline to a reasonable number of decimal places and move on.

novinosrin
Tourmaline | Level 20

Master @data_null__  Salute you always 

 

data _null_;  
   do i=1 to 50;
      base = ranuni(1234)*10;
      aval = ranuni(2345)*10;
      chg1 = round(divide((aval-base),base)*100,.01);
      chg2=(aval-base)/base;
      chg2=round(chg2*100,.01);
	  k=chg1=chg2;
	  
      if chg1 ne chg2 then do;
         put (base aval chg1 chg2) (=best16.);
         put (chg1 chg2) (=hex16.) /;
         end;
        else put "They are equal!";
      end;
   run;
Kurt_Bremser
Super User

@himalayan wrote:
, but they keep sending me to the same numeric precision documents

 


That is because, at the core, it is always necessary to round numbers before making checks for equality. Any mathematical operation with numbers stored in binary real format is bound to create those small binary artifacts that need to be filtered out.

While the difference here has obviously been fixed (and was fixable!) between 9.3 and 9.4, other differences WILL happen, and you need to take care of that proactively. These differences are no errors, they happen by nature and cannot be fixed.

ballardw
Super User

Division is not nice in general. You may want to consider controlling the number of decimals involved before the division and afterwards by rounding if this is an issue.

Tom
Super User Tom
Super User

Running on RedHat Linux I only found differences with SAS version 9.1 (TS1M3) 

No differences using 9.2 (TS2M3), 9.3 (TS1M2), or 9.4 (TS1M5).

Check your maintenance release level.

Also note how long ago these older versions of SAS were released (or better supplanted).

https://blogs.sas.com/content/iml/2013/08/02/how-old-is-your-version-of-sas-release-dates-for-sas-so...

 

 

himalayan
Fluorite | Level 6

Thanks Tom and everyone else who replied. For the time-being it looks like we will have to change the legacy code to include rounding and put it our programming specs. 

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 14 replies
  • 4279 views
  • 3 likes
  • 8 in conversation