Following is a little script for calculating mortgage payment, the crux here is the data calculation, instead of implement the internal Date class that java provided, I “dumbly” wrote a data class myself, luckily it worked, and by doing this the calculation of dates are no longer a black box, the details of the calculation are revealed below.

import java.util.Scanner;

class Date {

//data members

private int year;

private int month;

private int day;

public static int[] days_leap={31,29,31,30,31,30,31,31,30,31,30,31};

public static int[] days_nonleap={31,28,31,30,31,30,31,31,30,31,30,31};

//default constructor

Date(){}

//constructor with parameter

Date(int ds){

day=ds0;

month=((ds-day)000)/100;

year=(ds-month*100-day)/10000;

}

//static member function for determine leap year or not

public static boolean IsLeap(int d){

boolean result=false;

if(d%4==0 && d0!=0 || d@0==0)

result=true;

else

result=false;

return result;

}

//day counting function

public static int day_counter(Date d1,Date d2){

int period=0;

//if d1 is later than d2,reverse it

if((d1.year10000+d1.month100+d1.day)>(d2.year10000+d2.month100+d2.day))

{

return day_counter(d2,d1);

}

else{

//not same year

if(d1.year!=d2.year){

//first: days between intermediate years

for(int i=d1.year+1;i<=(d2.year-1);i++){

if(IsLeap(i)==false)

period+=365;

else

period+=366;

}

//second: days in first year

if(IsLeap(d1.year)==false){

for(int j=d1.month+1;j<=12;j++){

period+=days_nonleap[j-1];

}

period=period+days_nonleap[d1.month-1]-d1.day;

}

else{

for(int j=d1.month+1;j<=12;j++){

period+=days_leap[j-1];

}

period=period+days_leap[d1.month-1]-d1.day;

}

//third: days in last year

if(IsLeap(d2.year)==false){

for(int j=1;j<=d2.month-1;j++){

period+=days_nonleap[j-1];

}

period=period+d2.day;

}

else{

for(int j=1;j<=d2.month-1;j++){

period+=days_leap[j-1];

}

period=period+d2.day;

}

return period;

}

//on the same year

else{

if(IsLeap(d1.year)==false){

for(int i=d1.month+1;i<=d2.month-1;i++){

period=period+days_nonleap[i-1];

}

period=period+d2.day+days_nonleap[d1.month-1]-d1.day;

}

else{

for(int i=d1.month+1;i<=d2.month-1;i++){

period=period+days_leap[i-1];

}

period=period+d2.day+days_leap[d1.month-1]-d1.day;

}

return period;

}

}

}

//change the data of a member

public void setDate(int y,int m,int d){

this.year=y;

this.month=m;

this.day=d;

}

//function for determine future date

public static Date Future_date(Date d,int m){

Date result=new Date(19900101);

//checking if this original date is month end or not

boolean end=true;

if(IsLeap(d.year)==true){

if(d.day==days_leap[d.month-1]){

end=true;

}

else{

end=false;

}

}

else{

if(d.day==days_nonleap[d.month-1]){

end=true;

}

else{

end=false;

}

}

//do not cross year

if(d.month+m<=12){

if(IsLeap(d.year)==true){

if(end=true){

result.setDate(d.year, d.month+m, days_leap[d.month+m-1]);

return result;

}

else{

int tempday=0;

tempday=d.day>days_leap[d.month+m-1]?days_leap[d.month+m-1]:d.day;

result.setDate(d.year,d.month+1,tempday);

return result;

}

}

else{

if(end==true){

result.setDate(d.year, d.month+1, days_nonleap[d.month+m-1]);

return result;

}

else{

int tempday=0;

tempday=d.day>days_nonleap[d.month+m-1]?days_nonleap[d.month+m-1]:d.day;

result.setDate(d.year,d.month+1,tempday);

return result;

}

}

}

//cross years

else{

int tempyear=0;

int tempmonth=0;

int tempday=0;

if((d.month+m)==0){

tempmonth=12;

tempyear=d.year-1+(d.month+m)/12;

}

else{

tempyear=d.year+((d.month+m)-(d.month+m))/12;

tempmonth=(d.month+m);

}

if(IsLeap(tempyear)==true){

if(end==true){

tempday=days_leap[tempmonth-1];

result.setDate(tempyear,tempmonth,tempday);

//result.testsay();

return result;

}

else{

tempday=d.day>days_leap[tempmonth-1]?days_leap[tempmonth-1]:d.day;

result.setDate(tempyear,tempmonth,tempday);

//result.testsay();

return result;

}

}

else{

if(end==true){

tempday=days_nonleap[tempmonth-1];

result.setDate(tempyear,tempmonth,tempday);

//result.testsay();

return result;

}

else{

tempday=d.day>days_nonleap[tempmonth-1]?days_nonleap[tempmonth-1]:d.day;

result.setDate(tempyear,tempmonth,tempday);

//result.testsay();

return result;

}

}

}

}

//test function to see if i got things right

void testsay(){

System.out.print(this.year+" “);

System.out.print(this.month+" “);

System.out.print(this.day+" “);

}

}

public class loanAmortization {

private double loanAmt;

public double interestRate;

public int terms;

public Date startday;

//constructor

loanAmortization(double l,double i,int t,Date d){

this.loanAmt=l;

this.interestRate=i;

this.terms=t;

this.startday=d;//remains to be seen if i need shallow or deep

}

//function to determine remaining debt

public static double debt(double pmt,loanAmortization loan){

double remaining=loan.loanAmt;

int length=loan.terms*12;

Date startday=loan.startday;

Date head=startday;

double interest=0;

double principal=0;

for(int i=1;i<=length;i++){

Date next=Date.Future_date(startday,i);

//next.testsay();

int numday=Date.day_counter(head,next);

interest=remainingloan.interestRatenumday/365;

principal=pmt-interest;

remaining=remaining-principal;

head=next;

}

return remaining;

}

//function of bisect search

public static double bi_search(loanAmortization loan){

double result=0;

double head=loan.loanAmt/(loan.terms*12);//average payment, the debt would be left positive

double tail=loan.loanAmt;//pay all the amount each time, the debt would be left negative

if(debt(tail,loan)*debt(head,loan)<0)//if solution exists

{

double error=debt(head,loan)-debt(tail,loan);//difference of two points’s output

double mid=(head+tail)/2;

do{

if(debt(mid,loan)*debt(tail,loan)<0){

head=mid;

mid=(head+tail)/2;

error=debt(head,loan)-debt(mid,loan);

//result=mid;

result=(mid+head)/2;

}

else{

tail=mid;

mid=(head+tail)/2;

error=debt(mid,loan)-debt(tail,loan);

//result=mid;

result=(mid+tail)/2;

}

}while((tail-head>0.1)||error>0.1);// error

}

else{

System.out.println(“wrong starting bi-search parameter,check again”);

}

//System.out.println(tail-head);

System.out.println(result);

return result;

}

public static void main(String[] args) {

System.out.println(“Enter the loan amount:”);

System.out.println(“Enter the annual interest rate:”);

System.out.println(“Enter the terms in a year:”);

System.out.println(“Enter start date:”);

Scanner s1=new Scanner(System.in);

Scanner s2=new Scanner(System.in);

Scanner s3=new Scanner(System.in);

Scanner s4=new Scanner(System.in);

double loan=s1.nextDouble();

double interest=s2.nextDouble();

int term=s3.nextInt();

int d=s4.nextInt();

Date d1=new Date(d);

loanAmortization myloan=new loanAmortization(loan,interest,term,d1);

loanAmortization.bi_search(myloan);

}

}