C Program for Loan Amortization Schedule
Dean Douthat
dzd at cosivax.UUCP
Sat Apr 14 09:28:25 AEST 1984
In response to a request for software to compute amortization payments and
schedules, the following is submitted.
Tear along dotted line
------------------------------------------------------------------------------
/*
* Print amortization schedule for fixed-payment loan on sdtout.
*
* Usage: a.out amount annual term [month year [interval] ]
*
* amount = principal borrowed ($)
* annual = annual percentage rate of interest (%)
* term = length of loan (years)
* month = month (1-12) loan is made; default = current month
* year = year (00-99) loan is made; default = current year
* interval = months between payments (1,2,3,4,6,12); default = 1
*
* The load module should be placed in a file named "amort" and
* linked to a file named "amortp". The first will print assuming
* continuous form (with form feeds); the second assuming single
* sheet feed (with pauses before each page). Actually any names of
* five and six characters, respectively will suffice.
*
* Programmed by Dean Douthat
*/
#include <stdio.h>
#include <time.h>
#define EOS '\0'
static int month, year;
static float amount, annual;
static int term, interval, periods, pmts_per_year;
static long int balance, payment, interest;
static double periodic;
main(argc, argv)
int argc;
char *argv[];
{
int i, line, last, pause;
double x, r;
char *malloc();
/*
Add buffering to stdout in case it is redirected to raw printer output
that is, usually for a single user system. If output will always be
spooled, as on a multi-user system, this buffering can usually be omitted.
*/
setbuf(stdout, malloc(BUFSIZ) );
/*
Obtain inputs from command line arguments, check validity and supply
defaults if needed
*/
if(argc < 4)
{
fprintf(stderr,
"Usage: %s amount annual term [month year [interval] ]\n",
argv[0]);
exit(1);
}
pause = ( *(argv[0] + 5) != EOS );
sscanf(argv[1], "%f", &amount);
if(amount < 0.0) error("Illegal amount");
sscanf(argv[2], "%f", &annual);
if(annual < 0.0 || annual > 100.0) error("Illegal annual percentage");
sscanf(argv[3], "%d", &term);
if(term <= 0) error("Illegal term");
if(argc >= 6)
{
sscanf(argv[4], "%d", &month);
if(month < 1 || month > 12) error("Illegal month");
sscanf(argv[5], "%d", &year);
if(year < 0 || year > 99) error("Illegal year");
if(argc >= 7)
{
sscanf(argv[6], "%d", &interval);
if(interval < 1 || interval > 12 || (12 % interval) != 0)
error("Illegal interval");
}
else interval = 1;
}
else
{
today();
interval = 1;
}
/*
Set initial values
*/
pmts_per_year = 12/interval;
periodic = annual/(pmts_per_year * 100.0);
periods = term * pmts_per_year;
balance = amount * 100.0;
/*
Find periodic payment amount
*/
r = 1.0 + periodic;
for(x = 1.0, i = 0; i < periods; ++i) x *= r;
payment = (long) (100.0 * amount * periodic * x/(x - 1.0) + 0.5);
/*
Compute amortization table values
*/
for(i = 1; i <= periods; ++i)
{
interest = (long) (balance * periodic + 0.5);
if(last = (i == periods)) payment = interest + balance;
line = lineout(i, line, last, pause);
}
}
static long cum, ytd;
static int omonth, oyear;
static char *month_name[] =
{
"BAD",
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
lineout(i, line, last, pause)
int i, line, last, pause;
{
long princ_pay;
if(line < 4) /* Starting first page of output */
{
omonth = month;
oyear = year;
cum = 0.0;
line = header(pause);
}
if( (month += interval) > 12) /* Just finished a year */
{
ytd = 0.0;
++year;
month -= 12;
if(interval < 12)
{
putchar('\n');
++line;
}
if(line + pmts_per_year > 61) /* Page won't hold another year */
line = header(pause); /* Start next page */
}
princ_pay = payment - interest;
balance -= princ_pay;
cum += interest;
ytd += interest;
printf("%5d %s %02d",i,month_name[month],year % 100);
printf("%12.2f%12.2f%15.2f%15.2f%13.2f\n",princ_pay/100.0,
interest/100.0, balance/100.0, cum/100.0, ytd/100.0);
++line;
if(last)
{
printf("\n Last Payment = $%.2f",payment/100.0);
if(!pause) printf("\f\f");
}
return(line);
}
static char *type[] =
{
"BAD",
"monthly",
"bimonthly",
"quarterly",
"thrice-yearly",
"BAD",
"semi-annual",
"BAD",
"BAD",
"BAD",
"BAD",
"BAD",
"annual"
};
header(pause)
int pause;
{
if(pause)
{
fflush(stdout); /* Can be removed if "setbuf" removed in main */
fprintf(stderr, "Insert paper; type RETURN when ready ->");
getchar();
}
else putchar('\f');
printf("\n\n $%.2f at %2.3f%% annually for %d years starting %s %d\n",
amount,annual,term,month_name[omonth],oyear);
printf(" in %d %s payments of $%.2f",periods,type[interval],
payment/100.0);
printf("\n\n ");
printf("Principal Interest Balance Cum Int YTD Int");
putchar('\n');
return(7);
}
today()
{
struct tm *localtime(), *now;
long clock, time();
clock = time(NULL);
now = localtime(&clock);
month = now->tm_mon + 1;
year = now->tm_year;
if(month <= 0 || month > 12) month = 0;
year %= 100;
}
error(s)
char *s;
{
fprintf(stderr, "%s\n",s);
exit(2);
}
------------------------------------------------------------------------------
Tear along dotted line
Dean Douthat
UUCP: ...!sb1!mb2c!uofm-cv!cosivax!dzd | Mail: Zahntron, Inc.
Ma: (313) 995-9762 | 330 E. Liberty
MCI Mail: DDOUTHAT 187-3270 | Suite 3B
TWX/TELEX: 6501873270 | Ann Arbor, MI
Answerback: 6501873270 MCI | 48104
More information about the Comp.sources.unix
mailing list