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.
> >
>
|