turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

- Home
- /
- SAS Programming
- /
- General Programming
- /
- Please explain this divide by zero logic

Topic Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

07-30-2015 09:48 AM

Hello all,

I'm very much a SAS newbie (much more experienced in R!). I just started a job requiring the use of SAS for all analytics and so I'm definitely still getting used to it. I have a macro that I've created (tweaked from a somewhat different purpose) to calculate ratio variables on the fly. I was getting divide by zero errors in an earlier version of it, but after reading about using the IFN function to protect against those errors, the macro is now performing error free. The only problem is that I really don't understand what the IFN function is doing exactly in my macro. Here's the code:

**%macro** calculate_ratios(oldvarlist, suffix, divisor);

%let k=1;

%let old = %scan(&oldvarlist, &k);

%do %while("&old" NE "");

& old.&suffix = ifn(&divisor, &old. / ifn(&divisor, &divisor, **1**), **0** , **.**);

%let k = %eval(&k + 1);

%let old = %scan(&oldvarlist, &k);

%end;

drop &oldvarlist;

**%mend**;

I reference this macro in a later data step, where the divisor is a variable containing monetary totals, and oldvarlist is a macro variable containing variables constituting subcomponents of the monetary total variable. At first glance, to me the IFN function would seem to say "if the divisor is not missing or zero, then evaluate the second argument and return the result, otherwise evaluate/return the 3rd argument, and if missing return the 4th. However if I don't have that ifn encapsulating the divisor in the second argument then it returns a divide by zero error in the log file. Why should I need to use ifn on the divisor in the second argument, if that argument only comes into play when the &divisor in the first argument is nonzero/non-missing? The answer to this probably involves a perspective change on my part...

Thanks in advance!

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to matt_dubins

07-30-2015 10:37 AM

You are correct in your assumption. The ifn has the form:

ifn(<condition>,<value if true>,<value if false>)

Lets assume two conditions:

condition 1 - divisor is 0:

ifn(&divisor, &old. / ifn(&divisor, &divisor, **1**), **0** , **.**);

^ this is the result as condition is false (0)

&old is then divided by 1. Otherwise it would be &old / 0 which is where you get you divide by zero warnings.

condition 2 - divisor is 3:

ifn(&divisor, &old. / ifn(&divisor, &divisor, **1**), **0** , **.**);

^ this is the result as condition is true (!=0)

&old is then divided by 3. Otherwise it would be &old / 0 which is where you get you divide by zero warnings.

I would also point out that there really is no need for that macro code at all, there are better ways of coding - code generation, arrays, normalising data etc.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

07-30-2015 10:42 AM

But what use is the first argument then, if SAS evaluates the second argument even if the first argument is 0?

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to matt_dubins

07-30-2015 11:03 AM

Its probably a compilation order thing. I would word it as:

if &divisor. > 0 then &old.&suffix=&old. / &divisor;

Much clearer that way (apologies for the font changes here).

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

07-30-2015 11:06 AM

That makes sense. Would I have been able to code it that way in the macro?

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to matt_dubins

07-30-2015 11:36 AM

The second ifn accounts for the case when &divisor = 0.

You also want to consider what the first condition is, &divisor which could be anything. It really should be a condition, ie &divisor=0.

assuming divisor=0 and old=25:

1360 data want;

1361 x=ifn(0, 25 / 0, 0 , .);

NOTE: Division by zero detected during the compilation phase, detected at line 1361 column 13.

1362 run;

NOTE: The data set WORK.WANT has 1 observations and 1 variables.

NOTE: DATA statement used (Total process time):

real time 0.12 seconds

cpu time 0.00 seconds

1363 data want;

1364 x=ifn(0, 25 /ifn(0, 0, 1), 0 , .);

1365 run;

NOTE: The data set WORK.WANT has 1 observations and 1 variables.

NOTE: DATA statement used (Total process time):

real time 0.01 seconds

cpu time 0.00 seconds