LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (November 2005, week 1)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Wed, 2 Nov 2005 15:00:57 -0600
Reply-To:     Kevin Myers <KMyers@PROCOMINC.NET>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Kevin Myers <KMyers@PROCOMINC.NET>
Subject:      Re: Trying to avoid division by zero...
Content-Type: text/plain; charset="iso-8859-1"

By the way, here is an only slightly uglier macro to get around division by zero messages within expressions, if you really need to:

%macro zdiv(n,d); ifn(&d,(&n)/ifn(&d,&d,1),.) %mend zdiv;

Usage example:

data _null_; do d=0 to 5; r=%zdiv(1,d); put d= r=; end; run;

As provided above, this macro also avoids messages if the denominator is missing. Of course that could be changed very easily if desired.

s/KAM

----- Original Message ----- From: "Kevin Myers" <KMyers@ProcomInc.net> To: <SAS-L@listserv.uga.edu> Sent: Wednesday, November 02, 2005 11:42 AM Subject: Re: Trying to avoid division by zero...

> Unfortunately, the real culprit here is not the IFN function per se. The > "problem" lies with the way that the SAS interpreter *always* handles the > arguments of *any* function. All arguments of any function are always > evaluated before the argument *values* are passed to the function code for > execution. The interpreter has no way of knowing in advance that some > special functions may not always need some of their arguments to be > evaluated. SO, as you can see from this discussion (I hope) there is > actually no realistic way that the IFN function could behave in the desired > manner. > > s/KAM > > > ----- Original Message ----- > From: "Pudding Man" <pudding.man@gmail.com> > To: <iw1junk@comcast.net> > Cc: <SAS-L@listserv.uga.edu> > Sent: Wednesday, November 02, 2005 11:22 AM > Subject: Re: Trying to avoid division by zero... > > > > On Mon, 31 Oct 2005 22:35:43 +0000, iw1junk@COMCAST.NET (Ian Whitlock) > wrote: > > > > >I thought there would be a trivial macro answer > > > > Macro ??? > > > > >to Julie's question in > > >version 9, but I was shocked to find that > > > > > > data _null_ ; > > > input x y ; > > > z = ifn(missing(y) or y=0, . , x/y ) ; > > > put _all_ ; > > > cards ; > > > 1 0 > > > 5 . > > > 6 3 > > > ; > > > > > >produces missing value messages. Isn't this half the point of having the > > >IFN function? I feel cheated. > > > > V9 function IFN occurred to me also when I read Julie's > > post. Ian beat me to the test. > > > > From the V9 doc: > > ------------------------------------------------------------------- > > Syntax > > IFN(logical-expression, value-returned-when-true, > > value-returned-when-false <,value-returned-when-missing>) > > > > ... > > > > The IFN function uses conditional logic that enables you to > > select among several different values based on the value of > > a logical expression. > > > > IFN evaluates the first argument, then logical-expression. > > If logical-expression is true (that is, not zero and not > > missing), then IFN returns the value in the second argument. > > If logical-expression is a missing value, and you have a > > fourth argument, then IFN returns the value in the fourth > > argument. If logical-expression is false, IFN returns the > > value in the third argument > > ------------------------------------------------------------------- > > > > One might well assume that, if IFN was optimized for performance, > > it would evaluate arg1 and then compute only one of the > > following expressions. This doesn't appear to be the case. > > To wit (count the 'div. by 0' messages): > > > > 54 data _null_; > > 55 n=1; d=0; > > 56 junk = ifn(d, n/d , ., .); > > 57 put _all_; > > 58 run; > > > > NOTE: Division by zero detected at line 56 column 17. > > n=1 d=0 junk=. _ERROR_=1 _N_=1 > > n=1 d=0 junk=. _ERROR_=1 _N_=1 > > NOTE: Mathematical operations could not be performed at the following > > places. The results of > > the operations have been set to missing values. > > Each place is given by: (Number of times) at (Line):(Column). > > 1 at 56:17 > > ... > > 59 > > 60 data _null_; > > 61 n=1; d=0; > > 62 junk = ifn(d, n/d , n/d, .); > > 63 put _all_; > > 64 run; > > > > NOTE: Division by zero detected at line 62 column 17. > > NOTE: Division by zero detected at line 62 column 23. > > n=1 d=0 junk=. _ERROR_=1 _N_=1 > > n=1 d=0 junk=. _ERROR_=1 _N_=1 > > NOTE: Mathematical operations could not be performed at the following > > places. The results of > > the operations have been set to missing values. > > Each place is given by: (Number of times) at (Line):(Column). > > 1 at 62:17 1 at 62:23 > > ... > > 65 > > 66 data _null_; > > 67 n=1; d=0; > > 68 junk = ifn(d, n/d , n/d, n/d); > > 69 put _all_; > > 70 run; > > > > NOTE: Division by zero detected at line 68 column 17. > > NOTE: Division by zero detected at line 68 column 23. > > NOTE: Division by zero detected at line 68 column 28. > > n=1 d=0 junk=. _ERROR_=1 _N_=1 > > n=1 d=0 junk=. _ERROR_=1 _N_=1 > > NOTE: Mathematical operations could not be performed at the following > > places. The results of > > the operations have been set to missing values. > > Each place is given by: (Number of times) at (Line):(Column). > > 1 at 68:17 1 at 68:23 1 at 68:28 > > ... > > > > It appears that it computes (and issues messages for) all > > expressions coded in the IFN function, then returns the > > correct one. > > > > The doc doesn't say how the correct value is returned, so > > it isn't a "Real, Live Bug". To a material extent, they > > make a fine science of -not- writing doc such that much of > > anything can be technically called a "Bug". > > > > Of course, performance can be relatively miserable: > > > > 139 %let iter = 1e8; > > 140 > > 141 data _null_; > > 142 retain d 0 a b c 14; > > 143 do i = 1 to &iter; > > 144 junk = ifn(d, a , b, c); > > 145 end; > > 146 run; > > > > NOTE: DATA statement used (Total process time): > > real time 11.49 seconds > > cpu time 11.25 seconds > > 147 > > 148 data _null_; > > 149 retain d 0 a b c 14; > > 150 do i = 1 to &iter; > > 151 if d then junk = a; > > 152 else if d = 0 then junk = b; > > 153 else if missing(d) then junk = c; > > 154 end; > > 155 run; > > > > NOTE: DATA statement used (Total process time): > > real time 6.39 seconds > > cpu time 6.27 seconds > > > > "Parts" of the DATA step compile. Functions i.e. IFN > > interpret? It is practical to engineer an executable > > such as IFN to evaluate a logical expression and then > > compute only one of a list of subsequent expressions? > > > > What we have here is a "Design Error" (at least in the > > context of performance)? > > > > Note that this is -not- a "Version X.0" (i.e. SAS V9.0) > > problem. The code above ran in W2kP 9.1.3 SP3. I'm inclined > > to think we were all cheated. > > > > Zalut, > > Puddin' > > > > ***************************************************************** > > *** Puddin' Man PuddingDotMan at GmailDotCom ** > > *****************************************************************; > > > > Pease pudding hot, > > Pease pudding cold, > > Pease pudding in the pot > > Nine days old. > > >


Back to: Top of message | Previous page | Main SAS-L page