Monday, May 10, 2010

Doing Calculations in .NET

In the following example, I'm trying to do a basic mortgage payment calculation.  Assume that instead of hard coded values, I've collected these values from user input and validated them accordingly.

I know from doing application development for a bank before my number will be less than 1% of the loan amount and more than double the loan amount divided by the term (in months).

That means my range would be between about $1,100 (400,000 / 360) and $2,000 (200,000 x 1%).  That is a broad range but I should be somewhere in there.

But in fact, when I run my formula, I get 0.  My code is shown below.



What I like about this code is I showed what the math formula I was solving is.  That is about all I like about my code here.

The issues I have with this code:
1. Magic variables.  What do P, I, L, J, N, and M mean?  Since I have hard coded values here, it makes it easier to guess but its not very intuitive.

2. Since my formula is all bundled into one line, I can't check the intermediate steps to see where a potential problem is.

3. Some of these tasks might be useful in other areas but the code is not reusable.

4.  All my values are doubles because the Pow (Power) function requires a double as an input.  If I didn't do this, I'd end up having to cast all my variables.  Personally, I like to stick with the data type that is most reasonable for the data being contained, so I want to fix this.

Problem:  The actual problem in the code here is that I should be taking 1 - (1 + J)^N.  Instead, I'm doing (1 - (1+J))^N.  I get a number so small that it is effectively 0.

So, I've determined this code is hard to understand, test/maintain, and since I might not be the one supporting the code, I need to clean it up.

Here is an example of taking a formula and creating clean, reusable, and understandable code.

I cleaned this up by creating a top level function that wraps all the calculations (CalculateMonthlyPayment) but within that I actually break down each step of the formula so I could break point during debugging and see what the actual value(s) are.

Notice I also put the formula in the function that is calling calculate payment method.  This is so if another developer works on this, they know (without digging) what this code is doing.

Also notice that I'm able to use decimals instead of doubles now.  Tho, I do have to convert back to a decimal from a double in the CalculatePaymentRate function.

When I ran this, I found my bug and was able to fix the problem.


In summation, don't try to write calculations in one line they're hard to debug and easy to make mistakes.  Break your formula down into steps and solve each piece clearly so you can debug it.

No comments:

Post a Comment