/*=======================================================================*/ #define PROGRAMMER "SOLUTIONS, Nofrills" #define PROG_CODE "SOLN" #define COURSE "ECE-1021" #define YEAR (2004) #define TERM "Fall" #define SECTION (0) #define ASSIGNMENT "HW8" #define REVISION (0) #define TITLE "How much did that REALLY cost?" #define SUBTITLE "Last Modified on 09 NOV 04" #define EMAIL "ece1021@eas.uccs.edu" #define FILENAME "8_0SOLN0.c" /*=======================================================================*/ /*=======================================================================*/ /* WAIVED COMPILER WARNINGS */ /*=======================================================================*/ /* Linker Warning: No module definition file specified: using defaults Reason for Waiver: Can't suppress. Does not have adverse impact. */ /*=======================================================================*/ /* NOTES TO THE USER/GRADER */ /*=======================================================================*/ /* */ /*=======================================================================*/ /* PROBLEM STATEMENT */ /*=======================================================================*/ /* Determine the final cost and time to pay off a single item purchase on a typical credit card. Input: Item Cost Annual Percentage Rate Minimum Payment Percentage Minimum Payment Output: Monthly Activity Table giving Month #; Beg Balance; Finance Charge; Payment; New Bal; Min Due Summary giving Original Price, Months to Pay Off; Tot Fin Charges; Tot Cost */ /*=======================================================================*/ /* DEVELOPMENT NOTES */ /*=======================================================================*/ /* The following is the pseudocode presented in the steps in which it was developed (in the order it was developed as it was developed): 1) TASK: Get Data From User 2) TASK: Generate Table of Payments 3) TASK: Generate Summary 2) TASK: Generate Table of Payments 2.1) TASK: Initialize Data 2.2) TASK: Generate Table Header 2.3) TASK: Generate Table Month-by-Month 2.3) TASK: Generate Table Month-by-Month 2.3.1) WHILE: Item is not Paid Off 2.3.1.1) TASK: Generate the Activity for that Month 2.3.1.1.1) TASK: Print out Month Number 2.3.1.1.2) TASK: Print out Begining Balance 2.3.1.1.3) TASK: Print out Finance Charges 2.3.1.1.4) TASK: Print out Payment Credited 2.3.1.1.5) TASK: Print out Ending Balance 2.3.1.1.6) TASK: Print out Minimum Payment Due 3) TASK: Generate Summary 3.1) TASK: Output Original Purchase Price 3.2) TASK: Output Number of Months Required to Pay Off 3.3) TASK: Output Total Finance Charges Paid 3.4) TASK: Output Total Cost of Item 1) TASK: Get Data From User 1.1) TASK: Get Purchase Price 1.2) TASK: Get APR 1.3) TASK: Get Minumum Payment Percentage 1.4) TASK: Get Minimum Payment NOTICE that up to this point, not a single formula has been used. For the most part, the work so far has just been organizing the information in the problem statement into a list of tasks that must be performed. Bringing together what we have so far: 1) TASK: Get Data From User 1.1) TASK: Get Purchase Price 1.2) TASK: Get APR 1.3) TASK: Get Minumum Payment Percentage 1.4) TASK: Get Minimum Payment 2) TASK: Generate Table of Payments 2.1) TASK: Initialize Data 2.2) TASK: Generate Table Header 2.3) TASK: Generate Table Month-by-Month 2.3.1) WHILE: Item is not Paid Off 2.3.1.1) TASK: Generate the Activity for that Month 2.3.1.1.1) TASK: Print out Month Number 2.3.1.1.2) TASK: Print out Begining Balance 2.3.1.1.3) TASK: Print out Finance Charges 2.3.1.1.4) TASK: Print out Payment Credited 2.3.1.1.5) TASK: Print out Ending Balance 2.3.1.1.6) TASK: Print out Minimum Payment Due 3) TASK: Generate Summary 3.1) TASK: Output Original Purchase Price 3.2) TASK: Output Number of Months Required to Pay Off 3.3) TASK: Output Total Finance Charges Paid 3.4) TASK: Output Total Cost of Item Now we can fill in some of the computation involved: 3) TASK: Generate Summary 3.1) TASK: Output Original Purchase Price 3.1.1) OUT: Price 3.2) TASK: Output Number of Months Required to Pay Off 3.2.1) OUT: Month 3.3) TASK: Output Total Finance Charges Paid 3.3.1) OUT: TotFinCharge 3.4) TASK: Output Total Cost of Item 3.4.1) OUT: Price + TotFinCharge This tells us that we need for the "month" variable to be equal to the number of months in which payments were made. Since no payment was actually made in the first month, we will call that Month 0. This also tells us that we need to keep track of the cumulative finance charges as the item is paid off, but that we can calculate the total cost of the item with at the end using the Price and the total Finance Charges. 2.3.1.1) TASK: Generate the Activity for that Month 2.3.1.1.1) TASK: Print out Month Number 2.3.1.1.1.1) OUT: Month 2.3.1.1.1.2) SET: Month = Month + 1 (initialize to zero) 2.3.1.1.2) TASK: Print out Begining Balance 2.3.1.1.2.1) OUT: Balance (initialize to Price) 2.3.1.1.3) TASK: Print out Finance Charges 2.3.1.1.3.1) SET: FinCharge = Balance * MPR/100 (MPR = APR/12) 2.3.1.1.3.2) OUT: FinCharge 2.3.1.1.3.3) SET: TotFinCharge = TotFinCharge + FinCharge (ini to zero) 2.3.1.1.4) TASK: Print out Payment Credited 2.3.1.1.4.1) OUT: PayDue (initialize to zero) 2.3.1.1.5) TASK: Print out Ending Balance 2.3.1.1.5.1) SET: Balance = Balance + FinCharge - PayDue 2.3.1.1.5.2) OUT: Balance 2.3.1.1.6) TASK: Print out Minimum Payment Due 2.3.1.1.6.1) SET: PayDue = Balance * MinPct 2.3.1.1.6.2) IF: PayDue < MinPay 2.3.1.1.6.2.1) SET: PayDue = MinPay 2.3.1.1.6.3) IF: PayDue > Balance 2.3.1.1.6.3.1) SET: PayDue = Balance 2.3.1.1.6.4) OUT: PayDue This tells us what values need to be initialized to what at the beginning of TASK 2: 2.1) TASK: Initialize Data 2.1.1) SET: Month = 0 2.1.2) SET: Balance = Price 2.1.3) SET: PayDue = 0 2.1.4) SET: TotFinCharge = 0 The issue of rounding will be handled by rounding the payment due to the nearest cent once it is calculated. This will be done by multiplying the payment by 100 to convert it to cents, adding half a cent, truncating the result by calling the floor() function, and then dividing by 100. 2.3.1.1.6.4) SET: PayDue = floor(100*PayDue+0.5)/100 2.3.1.1.6.5) OUT: PayDue To avoid round off problems when we check to see if the item is paid off, we will require that the final balance be less than half a cent at which point we will call it paid in full. 2.3.1) WHILE: Balance > 0.005 (Item is not Paid Off) We can now flesh out our Input Prompts and Output Format: 1) TASK: Get Data From User 1.1) TASK: Get Purchase Price 1.1.1) OUT: "Enter the Original Purchase Price: (e.g. 2500.00):" 1.1.2) GET: Price 1.2) TASK: Get APR 1.2.1) OUT: "Enter the Annual Percentage Rate: (e.g. 17.9): " 1.2.2) GET: APR 1.3) TASK: Get Minumum Payment Percentage 1.3.1) OUT: "Enter the Minimum Payment Percentage (e.g. 2): " 1.3.2) GET: MinPct 1.4) TASK: Get Minimum Payment 1.4.1) OUT: "Enter the Minimum Payment Amount (e.g. 10.00): " 1.4.2) GET: MinPay 2.2) TASK: Generate Table Header 2.2.1) OUT: "MONTH | OLD BAL + FINANCE - PAYMENT = NEW BAL | PMT DUE" 3) TASK: Generate Summary 3.1) TASK: Output Original Purchase Price 3.1.1) OUT: "Originial Purchase Prince: $" Price 3.2) TASK: Output Number of Months Required to Pay Off 3.2.1) OUT: "Months to Pay Off: " Month 3.3) TASK: Output Total Finance Charges Paid 3.3.1) OUT: "Total Finance Charges : $" TotFinCharge 3.4) TASK: Output Total Cost of Item 3.4.1) OUT: "Total Cost of Purchase: $" Price + TotFinCharge Our Final-Full-Blown-Nothing-Left-Out Pseudocode is therefore: */ /*=======================================================================*/ /* PSEUDOCODE */ /*=======================================================================*/ /* 1) TASK: Get Data From User 1.1) TASK: Get Purchase Price 1.1.1) OUT: "Enter the Original Purchase Price: (e.g. 2500.00):" 1.1.2) GET: Price 1.2) TASK: Get APR 1.2.1) OUT: "Enter the Annual Percentage Rate: (e.g. 17.9): " 1.2.2) GET: APR 1.3) TASK: Get Minumum Payment Percentage 1.3.1) OUT: "Enter the Minimum Payment Percentage (e.g. 2): " 1.3.2) GET: MinPct 1.4) TASK: Get Minimum Payment 1.4.1) OUT: "Enter the Minimum Payment Amount (e.g. 10.00): " 1.4.2) GET: MinPay 2) TASK: Generate Table of Payments 2.1) TASK: Initialize Data 2.1.1) SET: Month = 0 2.1.2) SET: Balance = Price 2.1.3) SET: PayDue = 0 2.1.4) SET: TotFinCharge = 0 2.2) TASK: Generate Table Header 2.2.1) OUT: "MONTH | OLD BAL + FINANCE - PAYMENT = NEW BAL | PMT DUE" 2.3) TASK: Generate Table Month-by-Month 2.3.1) WHILE: Balance > 0.005 (Item is not Paid Off) 2.3.1.1) TASK: Generate the Activity for that Month 2.3.1.1.1) TASK: Print out Month Number 2.3.1.1.1.1) OUT: Month 2.3.1.1.1.2) SET: Month = Month + 1 (initialize to zero) 2.3.1.1.2) TASK: Print out Begining Balance 2.3.1.1.2.1) OUT: Balance (initialize to Price) 2.3.1.1.3) TASK: Print out Finance Charges 2.3.1.1.3.1) SET: FinCharge = Balance * MPR/100 (MPR = APR/12) 2.3.1.1.3.2) OUT: FinCharge 2.3.1.1.3.3) SET: TotFinCharge = TotFinCharge + FinCharge (ini to zero) 2.3.1.1.4) TASK: Print out Payment Credited 2.3.1.1.4.1) OUT: PayDue (initialize to zero) 2.3.1.1.5) TASK: Print out Ending Balance 2.3.1.1.5.1) SET: Balance = Balance + FinCharge - PayDue 2.3.1.1.5.2) OUT: Balance 2.3.1.1.6) TASK: Print out Minimum Payment Due 2.3.1.1.6.1) SET: PayDue = Balance * MinPct 2.3.1.1.6.2) IF: PayDue < MinPay 2.3.1.1.6.2.1) SET: PayDue = MinPay 2.3.1.1.6.3) IF: PayDue > Balance 2.3.1.1.6.3.1) SET: PayDue = Balance 2.3.1.1.6.4) SET: PayDue = floor(100*PayDue+0.5)/100 2.3.1.1.6.5) OUT: PayDue 3) TASK: Generate Summary 3.1) TASK: Output Original Purchase Price 3.1.1) OUT: "Originial Purchase Prince: $" Price 3.2) TASK: Output Number of Months Required to Pay Off 3.2.1) OUT: "Months to Pay Off: " Month 3.3) TASK: Output Total Finance Charges Paid 3.3.1) OUT: "Total Finance Charges : $" TotFinCharge 3.4) TASK: Output Total Cost of Item 3.4.1) OUT: "Total Cost of Purchase: $" Price + TotFinCharge As usual, we'll use functions to modularize the logic to keep the main() lean. */ /*=======================================================================*/ /* DEVIATIONS FROM SUBMITTED PSEUDOCODE */ /*=======================================================================*/ /* DEVIATION #1: The pseudocode as written does not waive the finance charge for the month that the balance is paid in full. 2.3.1.1.3) TASK: Print out Finance Charges 2.3.1.1.3.1) SET: FinCharge = Balance * MPR/100 (MPR = APR/12) 2.3.1.1.3.2) OUT: FinCharge 2.3.1.1.3.3) SET: TotFinCharge = TotFinCharge + FinCharge (ini to zero) Modified to: 2.3.1.1.3) TASK: Print out Finance Charges 2.3.1.1.3.1) IF: (Balance - PayDue) > 0.005 2.3.1.1.3.1.1) SET: FinCharge = Balance * MPR/100 (MPR = APR/12) 2.3.1.1.3.2) ELSE: 2.3.1.1.3.2.1) SET: FinCharge = 0 2.3.1.1.3.2) OUT: FinCharge 2.3.1.1.3.3) SET: TotFinCharge = TotFinCharge + FinCharge (ini to zero) DEVIATION #2: The variable "Payment" is added and, at the beginning of each loop, is set to "PayDue". The logic is unchanged, but this emphasizes that each month the payment that is being made it the minimum payment that is due. */ /*=======================================================================*/ /*=======================================================================*/ /* CODE SECTION */ /*=======================================================================*/ /*=======================================================================*/ /*== INCLUDE FILES ======================================================*/ #include /* stdout, putc(), printf(), scanf() */ #include /* EXIT_SUCCESS */ #include /* floor() */ /*== MACRO DEFINITIONS (OBJECT-LIKE) ====================================*/ #define FALSE (0) #define TRUE (!FALSE) #define BLANKLINE printf("\n") #define MARGIN (2) /* Left Margin in PrintHeader() */ #define INDENT_SIZE (2) /* Indent relative to */ #define LMARG printc(' ', MARGIN) /* Print Left Margin */ #define INDENT printc(' ', INDENT_SIZE) /* Indent relative to margin */ #define EMPTYLOOP {} /*== MACRO DEFINITIONS (FUNCTION-LIKE) ==================================*/ /*=======================================================================*/ /* SUPPORT FUNCTIONS ( functions not called directly by main() ) */ /*=======================================================================*/ int printc(char c, int n) { while ( (n--) && (c == putc(c, stdout)) ); /* EMPTY LOOP */ return n; } /*=======================================================================*/ /* PRIMARY FUNCTIONS ( functions called directly by main() ) */ /*=======================================================================*/ /*== FUNCTION PROTOTYPES (to Document Support Functions) ================*/ int printc(char c, int n); /*== PRIMARY FUNCTIONS ==================================================*/ void PrintHeader(void) { LMARG; printc('=', (78 - MARGIN)); putc('\n', stdout); LMARG; printf("Course....... %s-%i (%s %i)\n",COURSE,SECTION,TERM,YEAR); LMARG; printf("Programmer... %s (%s)\n", PROGRAMMER, PROG_CODE); LMARG; printf("Assignment... %s (Rev %i)", ASSIGNMENT, REVISION); LMARG; printf("(Source Code in %s)\n", FILENAME); LMARG; printf("Description.. %s\n", TITLE); LMARG; printf(" %s\n", SUBTITLE); LMARG; printc('=', (78 - MARGIN)); putc('\n', stdout); } /*=======================================================================*/ /* MAIN FUNCTION */ /*=======================================================================*/ /*== FUNCTION PROTOTYPES (to Document Primary Functions) ================*/ void PrintHeader(void); int main(void) { int Month; double PurchasePrice, apr; double MinimumPaymentPercentage, MinimumPaymentDollars; double Balance, PaymentDue, Payment; double FinanceCharge, TotalFinanceCharge; PrintHeader(); BLANKLINE; /* 1) TASK: Get Data From User */ printf(" Enter the Original Purchase Price: (e.g. 2500.00): "); scanf("%lf", &PurchasePrice); printf(" Enter the Annual Percentage Rate: (e.g. 17.9): "); scanf("%lf", &apr); printf(" Enter the Minimum Payment Percentage (e.g. 2): "); scanf("%lf", &MinimumPaymentPercentage); printf(" Enter the Minimum Payment Amount (e.g. 10.00): "); scanf("%lf", &MinimumPaymentDollars); /* 2) TASK: Generate Table of Payments */ /* 2.1) TASK: Initialize Data */ Month = 0; Balance = PurchasePrice; PaymentDue = 0.0; TotalFinanceCharge = 0.0; /* 2.2) TASK: Generate Table Header */ BLANKLINE; printf(" MONTHLY ACTIVITY:\n"); printf(" MONTH | OLD BAL + FINANCE - PAYMENT = NEW BAL | PMT DUE\n"); /* 2.3) TASK: Generate Table Month-by-Month */ while ( Balance > 0.005) { /* 2.3.1.1) TASK: Generate the Activity for that Month */ Payment = PaymentDue; printf(" %5i |", Month++); printf("%8.2f ", Balance); /* Old Balance */ if ( (Balance - Payment) > 0.005) /* No interest if paying off */ FinanceCharge = Balance * (apr/12.0)/100.0; /* (MPR = APR/12) */ else FinanceCharge = 0.00; printf("+%8.2f ", FinanceCharge); TotalFinanceCharge += FinanceCharge; printf("-%8.2f ", PaymentDue); /* From Prior Month */ Balance += FinanceCharge; Balance -= PaymentDue; printf("=%8.2f | ", Balance); /* New Balance */ PaymentDue = Balance * MinimumPaymentPercentage/100.0; if (PaymentDue < MinimumPaymentDollars) PaymentDue = MinimumPaymentDollars; if (PaymentDue > Balance) PaymentDue = Balance; PaymentDue = floor(100.0*PaymentDue+0.5)/100.0; printf("%8.2f \n", PaymentDue); } /* 3) TASK: Generate Summary */ BLANKLINE; printf(" FINAL SUMMARY:\n"); printf(" Originial Purchase Prince: $ %8.2f\n", PurchasePrice); printf(" Months to Pay Off: %5i\n", Month); printf(" Total Finance Charges : $ %8.2f\n", TotalFinanceCharge); printf(" Total Cost of Purchase: $ %8.2f\n", PurchasePrice + TotalFinanceCharge); return EXIT_SUCCESS; } /*=======================================================================*/ /* END OF SOURCE CODE FILE */ /*=======================================================================*/