一些租赁类和金融类项目可能会涉及到类似分期还款的还款表,专业名词叫租金表。算租金表的算法通常有等额租金(等额本息)、指定本金、等额本金等。稍有了解租金表的人都知道等额本息的算法,在excel中期利率是-PMT算法,日利率用规划求解,但是作为程序员,设计这个算法可能就不太方便。
首先看期利率的算法,这个有专用的公式,
先付:租金=P*I*(1+I)n-1/((1+I)n-1);
后付:租金=P*I*(1+I)n/((1+I)n-1);
细心一看可以发现,后付=先付*(1+I),没错,就是这样的。
其中P为本金,I为期利率,n为租赁其次。
写这个算法就是套用公式了,传入正确的参数即可。
日利率的等额本息,在excel中通常用规划求解进行计算,代码中的实现不太好处理,在此给出一种基于二分法的算法可供参考,处理还算比较简单。
/**
* 递归求解计算等额租金的等额值
*
* @param retsn 租金表总的期次
* @param amt 融资本金
* @param max 最大值,取本金的两倍
* @param min 最小值,取零,等额租金的租金值在区间(min,max)中,一般这个范围够了
* @param dayRate 日利率
* @param days 计算天数数组
* @return
*/
public static double getRetbal(int retsn,double amt,double max,double min,double dayRate,int[] days){
double mid = (max + min)/2;
//取中间值当做租金,去计算最后一期的剩余本金
double lvamt = getLvamt(retsn,mid,amt,dayRate,days);
//最后一期的剩余本金等于0或达到精度要求,则返回此租金
if(lvamt > 0 && lvamt < 0.000001){
return mid;
}
//若剩余本金小于0,则证明租金过大,从最小值到中间值,再用二分法,递归求解
if(lvamt < 0){
return getRetbal(retsn,amt,mid,min,dayRate,days);
}
//若剩余本金大于0且达不到精度要求,则证明租金过小,从中间值到最大值,再用二分法,递归求解
return getRetbal(retsn,amt,max,mid,dayRate,days);
}
/**
* 按照给定的租金和本金,得到最后一期的剩余本金并返回
*
* @param retsn 租金表总的期次
* @param retbal 租金
* @param lvamt 融资本金
* @param dayRate 日利率
* @param days 计算天数数组,计算利息用到
* @return
*/
public static double getLvamt(int retsn,double retbal,double lvamt,double dayRate,int[] days){
//逐期计算,得到最后一期的剩余本金并返回
for(int i = 0;i < retsn;i++){
double retint = lvamt*dayRate/100*days[i];
double retamt = retbal-retint;
lvamt -= retamt;
}
return lvamt;
}
在真正的项目中,直接使用double类型可能会导致精度丢失问题,建议换位BigDecimal,其中的signum()方法判断值的正负,doubleVlue()方法得到double类型数值。