William Smith is the engineering manager at Montana Software, a software development company specializing in custom applications for MS-DOS and Windows. You may contact him by mail at P.O. Box 663, Bozeman, MT 59771-0663.
The need in science and engineering for high-speed data processing was the original driving force behind the invention and the later improvement of computer hardware. It did not take long, however, before business became the largest user of computers and the driving force behind the improvement and diversification of computer software.
Presently, the largest volume categories of software applications are business-oriented. Business uses of computers and software cover such diverse applications as financial forecasting, economic modeling, accounting, tracking inflation, record keeping, materials planning, inventory, depreciation, document processing, taxes, and bookkeeping, to name just a few.
As a whole, business software is concerned with money. A central theme to business-oriented calculations and modeling is the time value of money. Loans, investments, rate-of-return calculations, depreciation, taxes, and cost/benefit analysis all require calculations based upon interest rates over periods of time. Nearly everyone has a loan, a bank account, or credit card. Interest rates and the resulting time value of money directly affects us all.
Computations that involve interest rates are tedious by hand. They require using interest rate tables to relieve some of the number pushing. Computer automation can easily handle these types of calculations.
More than a couple of times I have had to incorporate the equivalent of interest-rate tables into a software project. The relationships between the three quantities present value, future values, and equivalent uniform series form six basic formulas. These formulas are a function of interest rates and time expressed as number of periods.
The theory of compounding, or how often you calculate the interest, further complicates matters. Calculations with continuous compounding requires an additional set of six formulas.
In total, there are twelve interest rate formulas that I have utilized when writing business applications. These formulas eventually became a small library of C functions and macros that I have used many times. They are simple, small, and constitute a useful addition to your library and arsenal of programming tools.
There are additional interest rate formulas for increasing series of values known as gradients. I have never had to use these formulas, so they have not appeared in my financial function library yet.
Numeric Money Types
When writing a business application in C, one of the first stumbling blocks you will come up against is which numeric type works best to represent money. Representing money values in C is a challenge. Floating-point and integer types have some contrasting pros and cons. Using a floating-point value to represent money has the problem of requiring a conversion to fixed point. This requires rounding off and can eventually lead to round-off error. Using an integer value has the disadvantage of not covering a large enough range of values under some compiler/operating system combinations.C-library vendors have addressed these problems by offering business-math libraries. There are many business-math libraries available that each vendor claims overcomes the problems of round-off error and range. I have never used any so I cannot make any statements as to whether they overcome some of the problems that developers typically encounter when working with money.
For the interest-rate functions, I choose to use the standard floating-point type double. I choose this because the functions work with interest rates and periods. Neither of these is a money type. Interest rate is a true floating-point value. The number of periods is an integer value. The value returned by the functions is also a floating-point value. You use this value on or with money values, but it is not a money value. This gets the interest-rate functions out of the dilemma of having to commit to a best way to represent a money type. It is up to the user of the functions to determine how best to handle rounding and representation of money values.
Interest-Rate Formulas
The basic requirements of interest calculations involve working with the concepts of present values, future values, and equivalent uniform series of values. The relationships between these three quantities depend upon interest rates and time. For the purpose of the formulas, time is broken up into periods. The interest rate values must apply to the same period.There are six possible relationships between the three values of present value (P), future value (F), and equivalent uniform series of values (A). Table 1 contains some symbols and definitions that the interest rate formulas use.
The relationships between A, F, and P are represented by ratios between the values. Each of the six formulas calculate one of the possible six ratios. The relationship or ratio depends only on the interest rate and number of periods.
Table 2 lists the six relationships for discrete compounding. The table includes the formula as a function of interest rate (i) and number of periods (n). The formulas and functions require the interest rate as a floating-point number, not a percentage. The table also lists the symbolic representation of the formula as a ratio between A, F, or P. The first column in the table is the name of the C-function rendition of the formula.
The formulas in Table 2 assume discrete compounding. They expect the interest rate to apply to the same period as the compounding frequency. As long as this criterion holds, these formulas will work for any interest rate and number of periods. If the compounding frequency is different from the interest period, the number of periods and interest per period must be converted into values adjusted for compounding periods and interest. This is done by dividing the interest rate by the compounding frequency per period and multiplying the number of periods by the compounding frequency.
For example, if the interest rate is 0.05 (5.0%) per period, the period length is one year, the number of periods is 10, and the compounding is monthly, you must adjust both the interest rate and the number of periods to use the formulas in Table 2. The interest rate (i) becomes
0.05 / 12 = 0.004167and the number of periods (n) are
10 * 12 = 120.Continuous compounding requires entirely different formulas. You can think of continuous compounding as increasing the compounding frequency to its absolute limit. The formulas still use an interest rate and the number of periods. Since the interest-rate period is no longer equal to the compounding period, the interest rate is no longer the effective interest rate, but a nominal interest rate (r). The nominal interest rate does not include the effect of compounding.Table 3 lists the six interest-rate formulas and functions for continuous compounding. The symbolic representation of the formulas is the same as in Table 2. The Symbols column is a ratio between A,F, or P. I have changed the C function names by adding _c to the end of the name. This indicates that the function is for continuous compounding. The formulas depend upon the nominal interest rate per period and the number of periods. In addition, the formulas use the constant e (natural log base).
Functions and Macros
Listing 1, FINANCES.C, contains the twelve functions listed in Table 2 and Table 3. These functions are interdependent. They make calls to one another. I have optimized these functions for size. The functions are as terse as possible. They rely upon the similarities between one another to keep them short and compact. This may take the least amount of overall code space, but is not the fastest rendition possible. For those who need speed, Listing 2, FINANCES.H contains macro equivalents to the functions in Listing 1. I have optimized the macros for speed. The macros avoid calling any of the functions in Listing 1. Listing 2 also contains prototypes for all the functions in Listing 1.If you want to create a hybrid of these two versions you can change the way each function is coded. Just include a call to a macro inside a function wrapper. For example you can rewrite the function a_to_f as
double a_to_f( double i, int n ) { return ( A_TO_F( i, n ) ); }This would speed up the functions by avoiding interdependency and calls to other functions in the library.Here is an example of using the functions to calculate the monthly payment required to pay back a $100,000.00 loan in 30 years with a 8% annual interest rate. This is a typical mortgage these days.
Payment = 100000.0 * p_to_a( 0.08 / 12.0, 30 * 12 );(Monthly payment is $733.77)
Conclusions
Calculations involving interest rates are fundamental to business and financial software. This library of functions presents a set of tools. They are building blocks you can use to add time value of money features to your applications. I have used them in applications ranging from a simple Real Estate loan-calculation program to a sophisticated financial-modeling application.Do not underestimate their utility. The Real Estate loan calculation program was extremely simple. It consisted of nothing more than a very easy to use interface on top of these functions. I created this program as a vertical application for some local realtors who were computer-illiterate and computer-intimidated. For a very small amount of work it garnered a handsome rate of return.