一些租赁类和金融类项目可能会涉及到类似分期还款的还款表,专业名词叫租金表。算租金表的算法通常有等额租金(等额本息)、指定本金、等额本金等。稍有了解租金表的人都知道等额本息的算法,在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类型数值。