Calculating Loan Payments: Rounding Correctly?

  • Thread starter Thread starter newageanubis
  • Start date Start date
AI Thread Summary
The discussion focuses on calculating the monthly payment for a loan and the proper method for rounding to two decimal places in C programming. The initial approach using the printf statement was questioned for its rounding accuracy. It was clarified that printf may truncate rather than round, depending on the compiler, particularly with Microsoft compilers which generally round correctly. The conversation delves into the complexities of floating-point representation under the IEEE standard, highlighting that certain numbers may not be represented exactly, leading to unexpected results in rounding. An example code snippet illustrates the issue, showing that even if a number like 37.785 is intended to round up, it may actually round down due to its IEEE representation. The discussion also touches on alternative rounding methods, including adding a small value before truncation to achieve the desired rounding effect, emphasizing that rounding is more nuanced than simple arithmetic operations.
newageanubis
Messages
15
Reaction score
0
Hey everyone,

I'm writing a simple program to calculate the monthly payment amount for a loan given a principal, down payment, finance term, and interest rate. The monthly payment needs to be reported to the user rounded to two decimal places after they have entered all the required information. The assignment instructions specify that the monthly payment should be rounded to two decimal places, not truncated, floored, ceiled (?), etc.

To accomplish this, I have used the conversion specification in the printf statement to specify that the monthly payment should be printed to two decimal places:

"printf("The monthly payment amount is: %.2lf", downPayment);"

Does this method round properly, or does it just truncate? Will it produce the same results as multiplying the monthly payment by 100, using the round function from math.h to round the result, and then dividing by 100?

Thanks!
 
Technology news on Phys.org
What you show doesn't do any rounding. It's just truncating the result after the 2nd decimal place. So no, it doesn't produce the same results as actual rounding.
 
Depending on the compiler, printf output will generally round floating point numbers, but I don't think there's any rule in C / C++ that requires rounding. Microsoft compilers will round with printf.
 
rcgldr said:
Depending on the compiler, printf output will generally round floating point numbers, but I don't think there's any rule in C / C++ that requires rounding. Microsoft compilers will round with printf.
The standards are fairly tight with respect to rounding.

However, there is an issue here. If your computer is using the IEEE floating point standard (almost every computer nowadays), a floating point number doesn't represent just one number. It instead represents a range of numbers. Every number in that range will have the same IEEE representation. Consider the two numbers 19810222/219 + 21474836/247 and 37785/1000. These two numbers have the same representation in the IEEE double precision format. The first number is "exact"; it's IEEE representation is exactly equal to the 19810222/219 + 21474836/247. The latter number, 37785/1000 (or 37.785), is not an exact number.

Consider the following C code:
Code:
#include <stdio.h>
int main () {
   double x1, x2;
   long int two_pow19 = 1L << 19;
   long int two_pow47 = 1L << 47;

   x1 =  37785.0 / 1000.0;
   printf ("37.785 rounded = %.2f\n", x1);

   x2 = 19810222.0/two_pow19 + 21474836.0/two_pow47;
   printf ("19810222/2^19 + 21474836/t2^47 rounded = %.2f\n", x2);

   printf ("x1-x2 = %.15g\n", x1-x2);

   printf ("x1*2^47 = %.2f\n", x1*two_pow47);

   return 0;
}

Even if you are of the opinion that 37.785 should be rounded to 37.79 (opinions do vary, and so do different versions of the C library), most computers will print 37.785 as 37.78. That's because the exact number in the range of numbers that have the same representation is 19810222/219 + 21474836/247, or approximately 37.7849999999999966. Assuming you are using the default rounding mode, that number should be rounded down to 37.78. So it is -- even if you meant 37.785 and even if you want those corner cases to be rounded up.

Now consider the following Excel formulae in two cells:
Code:
=ROUND(37785/1000,2)
=ROUND(19810222/2^19+21474836/2^47,2)

Excel will display 37.79 as the value of both cells. Excel looks to see whether the range of numbers represented by some IEEE representation contains the corner case, in this case 37.785. That corner case rounds up per Excel's rounding rules, so 37.785 is rounded up to 37.79, but so is 37.7849999999999966.
 
yeah, I thought that was always the case...%W.df rounds to d decimal places...that's what I have always assume in tcl, C, fortran, python, java...
 
If you want to round to 2 decimal places, you can add .005 then truncate it. You should be able to generalize it to what ever precision you want.
 
e.g:- rounding of 10.457 to the nearest 2 decimal places

(integer(10.457*100+0.5))/100 = 1046/100 = 10.46

for 3 decimal places *1000 and then /1000
 
Last edited:
Do that with my example of 37.785.

Addendum
Or, for that matter, if your computer is as goofy as mine (and it almost certainly is), try 0.145, 0.285, 0.565, and 0.575. The next problem child doesn't occur until after 1. In the 1s, you have 1.005, 1.015, 1.025, 1.035, 1.125, 1.135, 1.145, 1.155, 1.255, 1.265, and 1.275. And so on.

Rounding isn't quit as simple as multiplying by 10n, adding 1/2, casting to an integer, and dividing by 10n. At least not if you want to do it right.
 
Last edited:

Similar threads

Back
Top