Discussion in 'Mac Programming' started by CSJoe, Jan 10, 2007.

1. CSJoe macrumors newbie

Joined:
Jan 10, 2007
#1
I have recently been set a piece of homework that is causing me many a problem.

I need to implement a class named InterestSolver that extends the abstract class InterestSolverDefn. Given any three of the four parameters: yearly interest rate, monthly repayment amount, initial sum borrowed and time of loan in months; these methods will allow the fourth to be computed.
The abstract class Interest SolverDefn follows below followed by the homeowork question

/**
* Abstract class definition for a simple class to compute
* one of the interest rate, monthly repayment amount, initial
* premium and number of months of loan given the other three.
*
* This particular definition prescribes the bisection
* method to solve the resultant non-linear equation for
* obtaining the interest rate. Netwon's method would also be
* a possibility.
**/

public abstract class InterestSolverDefn {

/**
* Mutator for setting the rate of interest
* @param givenRate New rate of interest value
* @throws IllegalArgumentException if parameter not >0 and <100
**/
public abstract void setRate (double givenRate);

/**
* Mutator for setting the monthly repayment amount
* @param givenRepayment the new amount for the monthly repayment
* @throws IllegalArgumentException if parameter <=0
**/
public abstract void setRepayment(double givenRepayment);

/**
* Mutator for setting the number of months in the loan period
* @param givenMonths New length of loan period in months.
* @throws IllegalArgumentException if parameter <=0
**/
public abstract void setMonths(int givenMonths);

/**
* Mutator for setting the amount of the initial loan
* @param givenPremium New amount of initial loan
* @throws IllegalArgumentException if parameter <=0
**/

/**
* Accessor for obtaining the current setting of the interest rate
* @return The current value of the interest rate
**/
public abstract double getRate ();

/**
* Accessor for obtaining the current value of the monthly repayment
* @return The current value of the monthly repayment
**/
public abstract double getRepayment();

/**
* Accessor for obtaining the current loan period in months
* @return The current loan period in months
**/
public abstract int getMonths();

/**
* Accessor for obtaining the current value of the initial loan
* @return The current value of the initial loan
**/

/**
* Method to compute the monthly repayment given the rate of interest,
* loan period in months, and value of initial loan
**/
public abstract void computeRepayment();

/**
* Method to compute the value of initial loan given the rate of interest,
* loan period in months, and value of the monthly repayment
**/

/**
* Method to compute the loan period in months given the rate of interest,
* the monthly repayment, and value of initial loan
**/
public abstract void computeMonths();

/**
* Method to compute the rate of interest given the monthly repayment,
* loan period in months, and value of initial loan
**/
public abstract void computeRate();

/**
* Implementation of the bisection method to solve the single nonlinear
* equation associated with computing the interest rate given the other
* three values.
* @param a The value of the left hand end of an interval containing
* the root of the function f (see below)
* @param b The value of the right hand end of an interval containing
* the root of the function f (see below)
* a and b must be chosen so that f(a)*f(b)<0. In fact this
* is guaranteed the values are set according to the details
* given in the tutorial sheet. It is sensible to check anyway!
* @param eps Value controlling the accuracy of the final approximation
* to the root. See the description in the tutorial sheet for
* full details on how this should be used.
* @return An approximation to the root of f(J) = 0. This is a simple
* function of the interest rate.
* rate = 1200*(root - 1)
* @throws RuntimeException If f(a)*f(b)>0 on entry or the requested
* accuracy cannot be met
* @throws RuntimeException if size of repayment is too small to cover
* interest, making it impossible to pay off the loan
**/
protected abstract double bisection(double a, double b, double eps);

/**
* Function defining the non-linear equation being used by the bisection
* method to compute the interest rate. This should be the equation
* given in the assessment sheet that is obtained by using the
* geometric sum and clearing the (1-J) denominator to generate a
* simple (m+1) degree polynomial.
* @param J Value at which the function is to be evaluated
* @return The value of f(J)
**/
protected abstract double f(double J);
}

Theory
An amount £P is borrowed at an annual rate of interest of I%. At the end of each month £R is repaid and the whole debt is to be paid off in m months.
We assume that each month is considered to be 1/12 of a year and that the interest is calculated for each month of the loan on the outstanding amount at the start of each month.
If the amount owed at the end of month 1 is denoted by P1 we have
P1 = (P + I * P/1200) − R
= P(1 + I/1200) − R
Similarly at the end of month 2 the amount owed is given by
P2 = P1(1 + I/1200) − R
= (PJ − R)(J) − R
= PJ^2 − RJ − R
where J = (1 + I/1200).
Continuing in the same way we get
P3 = PJ^3 − RJ^2 − RJ − R
and in general
Pm = PJ^m − RJ^m−1 − RJ^m−2 − ... − R
= PJ^m − R(1 + J + J^2 + ...+ J^m−1)
The term in the final brackets is a geometric sum and may be written as
1 − J^m
--------------
1 − J
Note: This is only valid if J != 1 which is alright because this means that I = 0 which is a trivial case we probably arent interested in. However, keep this in mind in what follows.
Thus
Pm = PJ^m − R(1 − J^m)
----------------
1 − J
and if we require the loan to be paid off after m months then
Pm = 0 or PJm = R(1 − Jm)
--------------
1 − J
This gives us a way of computing P and R given the other three quantities:
P = R(1 − J^m)
-------------
J^m(1 − J)
R = PJ^m(1 − J)
---------------
1 − J^m
By rearranging we can also isolate m
R − RJ^m = PJ^m(1 − J)
R = J^m(P(1 − J) + R)
Jm = R
------------------
P(1 − J) + R
mlog J = logR − log(P(1 − J) + R)
m = logR − log(P(1 − J) + R)
-------------------------------
log J
Finally we need to be able to compute J (and hence I). Before you start trying to compute I what condition needs to hold between the other three quantities to ensure that the calculationmakes sense?
In what follows we make things as simple as possible so that the function we have to deal with is easy to compute. But note that we have multiplied through by (1 − J) and this leads to a spurious root at 1. This makes us have to think just a little bit later on.
R − RJ^m = PJ^m − PJ^m+1
PJ^m+1 − (R + P)J^m + R = 0
and to compute J requires the solution of the single nonlinear equation
f(J) ≡ PJm+1 − (R + P)Jm + R = 0
Implementation
The assessment requires you to solve this equation using the bisection method. To do this successfully you need to be able to generate two values JL and JR so that the interval
JL ≤ J ≤ JR contains the required root. If the value of I is known to be greater than zero and less than 100, then we know that the value of J is constrained to be in the range
1 < J ≤ 1 1/12 . Thus the obvious values to use for the left and right interval points for the bisection method are 1 and 1.08333. However we cant use 1 as f(1) is zero and we need the function to be of the opposite signs at the end points.
It isnt hard to convince yourself that the value of f(J) is positive for 0 < J < 1 by computing the turning points of f(J), i.e., the points where the derivative is zero
f′(J) = (m+ 1)PJ^m − (R + P)mJ^m−1 = 0
i.e. J^m−1(JP(m+ 1) − m(R + P)) = 0
whence either
J = 0 or J = m(R + P)
------------
P(m+ 1)
The second value may be used as the left hand end-point (Why?).
Even though the values discussed above for choosing JL and JR should guarantee f(JL) * f(JR) < 0 there is no harm done in testing that this condition does in fact hold within your implementation of the bisection method. This idea of defensive programming is important and, since its so cheap anyway, not worth the savings gained from not doing it (Note: this may not always be the case). Such error traps are useful both in the debugging phase of the implementation and during upgrades to the software. Whats more, if everything else has been computed correctly, this test can be used to detect impossible data  what conditions arent met?
The way in which the iteration within the bisection method is controlled is important. We really dont need the interest rate computed to more than 3 significant figures. We might be tempted to use a stopping criterion of the form
|JL − JR |
|---------| <e
| JMIN |
where JL and JR are the end-points and JMIN the mid-point of the current interval. Unfortunately J isnt the quantity we want, we are really looking for an accurate estimate of J −1. (Why is this
a problem?)
Hence a better stopping criterion is
|(JL − 1) − (JR − 1) |
|------------------ | <e
| JMID − 1 |
which you should be able to simplify a little! Choose a suitable value of ǫ to generate an interest rate of at least 3 significant figures.
Results for the premium and repayment calculations should be given to the nearest penny and, for the month calculation to the number of months necessary to pay off the loan (e.g., 3.1 months would be returned as 4). The annual interest rate should be returned correctly rounded to 2 significant decimal digits (e.g., 10.42%).
The bisection method must be implemented non-recursively and your implementation should seek to use the minimum number of function evaluations.

2. mbabauer macrumors regular

Joined:
Feb 14, 2006
#2
What exactly is the problem? You will get better help by stating a more exact problem you are having. Posting your homework assignment and expecting someone to code it for you will most likely not happen.

3. mufflon macrumors 6502

Joined:
Sep 15, 2006
#3
easiest way to deal with this kind of assigment is to simply focus on separate functions at a time, do a function at a time until you're complete and able to test the whole package. Read thorugh the thory part and think about how you'll set this up before you go waltzing into the unknown - do this and you'll have less issues (hopefully)

4. CSJoe thread starter macrumors newbie

Joined:
Jan 10, 2007
#4
I know I am to look over each function seperately before implementation, the problem I am having though is actualy getting my head round any of it. At a first glance it is overwhelming and comes across as a foreign language. I am not sure of a good place to start and am having difficulty coming up wth a solution even for the first question.

5. mufflon macrumors 6502

Joined:
Sep 15, 2006
#5
well you need to define a certain amount of variables:

rate
months
inital loan

these are defined by your setXXXXX

you are then to calculate based on the formulas you find in "Theory".

e.g. month1 = initial lone * rate / month
month2 = month1 * rate / month
(=> monthX = inital lone * (rate / month) ^ X)

so my advice is to sit down and code the "set"-methods and continue reading your theory some more, alternatively write down what you need to know based on the variables you have, every method says what it computes based upon what criterias are used.

A good way to become more proficient with anything is to debate and discuss with your classmates - either do that, ask your teacher or ask more exact questions here - we are not here to make the work for you (you will have severe issues if we do when you do your exam!) - just give you pointers and a friendly nudge *nudge*

some stuff are really advanced when you look at it initially - but one usually get the hang of it sooner or later.

edit: might mention that my formula isn't really supposed to be the same as the one described in the theory part - it's just there for "this is a good starting point theory wise" - your assigment is a bit more advanced, but not overly much

6. Llywelyn macrumors member

Joined:
Oct 27, 2003
#6
Design it.

Breathe.

Write a set of input-output pairs. "For this method, if I put in these values, I will get this result."

Look at each method and see what it needs to do.

Remember, every big problem is just a collection of small problems. So solve those "small problems."

On a side note, I'd say the class given here has rather poor design, but eh.