# Building Log & Antilog Functions with Proc FCMP

by ‎09-25-2017 04:27 AM - edited ‎09-25-2017 04:27 AM (1,142 Views)

• ,

• ,

## Introduction

I was recently working on a new piece of code which required me to use the logarithm of a number to base 0.5 (don’t ask – that may form the basis of a future article :-)). My immediate reaction was “no problem - there’s a function for that”. However, upon checking I realised that there isn’t an inbuilt SAS function you can use to give you a logarithm to just any base; the log function itself returns the natural (base e) logarithm, the log1px function returns the log of 1 plus the argument, log10 gives you the logarithm to base 10 and log2 the logarithm to base 2. I knew that if I was working with Excel the log function there allows me to specify a base so I decided to use Proc FCMP to write my own user defined function to add to my growing library. In addition, once I’d completed that I decided it would be useful to have another function to convert a logarithm back to its source value and so the antilog function was born!

## The Logn Function

The formula for calculating the logarithm of a number to any given base is quite simple. You take the natural logarithm of the number and divide it by the natural logarithm of the base. This means we can create a nice short function like this (note that if the number is less than or equal to 0 we are returning a missing value – this is consistent with the inbuilt log functions).

``````/* Define the location of the UDF library */

libname udflib '/folders/myshortcuts/Dropbox/SAS/UDFLib';
options cmplib=udflib.funcs;

/************************************************************************************
Title: Logn

Purpose: Calculates the logarithm of a number to a supplied base

Restriction: None

Syntax: Logn(value, base)

Required Arguments: Two positive numeric constants, variables or expressions

Details: The logn function returns the logarithm of the first argument to the base
of the second argument. If either argument is <= 0 then the function
returns a missing value

Examples: logn(32,0.5) - returns -5

************************************************************************************/

proc fcmp outlib=udflib.funcs.math;
function logn(val,base);
if (val <= 0) or (base <= 0) then return(.);
else return(log(val)/log(base));
endsub;
run;``````

## The Antilog Function

The formula to convert a logarithm back to its source number is also very simple – you just raise the base to the power of the logarithm and you have your original number like so

``````/* Define the location of the UDF library */

libname udflib '/folders/myshortcuts/Dropbox/SAS/UDFLib';
options cmplib=udflib.funcs;

/************************************************************************************
Title: Antilog

Purpose: Given a logarithm and it's base calculates the original number from which
it was derived

Restriction: None

Syntax: Antilog(value, base)

Required Arguments: Two numeric constants, variables or expressions

Details: The antilog function returns the orginal number from a logarithm given the
logarithm and it's base. If the base is <= 0 then the function returns a
missing value

Examples: antilog(-5,0.5) returns 32

************************************************************************************/

proc fcmp outlib=udflib.funcs.math;
function antilog(val,base);
if base <=0 then return(.);
else return(base**val);
endsub;
run;
``````

## Testing the Functions

Here is the log of a run creating a logarithm of a number to base 0.5 using logn and then converting it back with antilog. You can check the results with one of many online calculators

``````1          OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
61
62         libname udflib '/folders/myshortcuts/Dropbox/SAS/UDFLib';
NOTE: Libref UDFLIB was successfully assigned as follows:
Engine:        V9
Physical Name: /folders/myshortcuts/Dropbox/SAS/UDFLib
63         options cmplib=udflib.funcs;
64
65         data _null_;
66
67         logval = logn(32,0.5);
68
69         put logval=;
70
71         antilogval=antilog(logval,0.5);
72
73         put antilogval=;
74         run;

logval=-5
antilogval=32
NOTE: DATA statement used (Total process time):
real time           0.18 seconds
cpu time            0.02 seconds``````

## Conclusion

Whilst in the vast majority of cases one of the inbuilt logarithm functions will be perfectly satisfactory you will, very occasionally, have the need for a different base and we now have a function sitting in our library waiting for just such an occurrence. As a bonus, we also have a means of converting any logarithm back to its original number.

If you think you can see an improvement to these functions or if there are any other functions you would like to see created please leave a comment below.

Contributors