java实现excel中的FV函数、PMT函数与PV函数工具类

1. 函数介绍

最近有用到计算一些投资现金与未来收益的场景,产品经理使用了excel公式 , 我也只能找找解决方法 。
参考:
  • 微软 PV函数
  • 微软 FV函数
  • 微软 PMT函数
这三个函数的计算,其实都是从一个数据公式代换来的:

2. 工具类与官方示例结果有不一样的地方

注意:下方展示的代码与excel中计算的结果相似,但是和微软的官方示例结果不同,官方示例的结果小数位不同
【java实现excel中的FV函数、PMT函数与PV函数工具类】不同之处--1:FV函数的结果不同
① 自己的excel公式计算结果
java实现excel中的FV函数、PMT函数与PV函数工具类


② 官方的示例结果
java实现excel中的FV函数、PMT函数与PV函数工具类


不同之处--2、官方示例excel对比
java实现excel中的FV函数、PMT函数与PV函数工具类


PV函数与PMT函数基本一样 , 只有四舍五入的区别 。

3. 工具类源码

/*** PMT 是一个财务函数 , 用于根据固定付款额和固定利率计算贷款的付款额 。** @param rate必需 。贷款利率 。* @param nper必需 。该项贷款的付款总数 。* @param pv必需 。现值 , 或一系列未来付款额现在所值的总额,也叫本金 。* @param fv可选 。未来值,或在最后一次付款后希望得到的现金余额 。如果省略 fv,则假定其值为 0(零),即贷款的未来值是 0 。* @param Type可选 。0或省略-期末,1-期初* @return*/private static double PMT(double rate, double nper, double pv, double fv, double type) {if (rate == 0) {throw new RuntimeException("缺少年利率");}double pmt = (pv*Math.pow(1(rate / 12), nper) fv)/((Math.pow(1(rate / 12), nper)-1)/(rate / 12))/(1(rate / 12)*type)*(-1);return new BigDecimal(pmt).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();}/***参考:https://support.microsoft.com/zh-cn/office/pv-函数-23879d31-0e02-4321-be01-da16e8168cbd** PV 是一个财务函数 , 用于根据固定利率计算贷款或投资的现值 。* 可以将 PV 与定期付款、固定付款(如按揭或其他贷款)或投资目标的未来值结合使用 。** @param Rate必需 。各期利率 。例如,如果您获得年利率为 10% 的汽车贷款,并且每月还款一次,则每月的利率为 10%/12(即 0.83%) 。您需要在公式中输入 10%/12(即 0.83%)或 0.0083 作为利率 。* @param Nper必需 。年金的付款总期数 。例如 , 如果您获得为期四年的汽车贷款,每月还款一次,则贷款期数为 4*12(即 48)期 。您需要在公式中输入 48 作为 nper 。* @param Pmt必需 。每期的付款金额,在年金周期内不能更改 。通常 , pmt 包括本金和利息,但不含其他费用或税金 。例如 , 对于金额为 ¥100,000、利率为 12% 的四年期汽车贷款,每月付款为 ¥2633.30 。您需要在公式中输入 -2633.30 作为 pmt 。如果省略 pmt , 则必须包括 fv 参数 。* @param fv可选 。未来值,或在最后一次付款后希望得到的现金余额 。如果省略 fv,则假定其值为 0(例如,贷款的未来值是 0) 。例如,如果要在 18 年中为支付某个特殊项目而储蓄 ¥500,000 , 则 ¥500,000 就是未来值 。然后,您可以对利率进行保守的猜测,并确定每月必须储蓄的金额 。如果省略 fv , 则必须包括 pmt 参数 。* @param type可选 。数字 0 或 1,用以指定各期的付款时间是在期初还是期末 。** PS: pmt与fv至少出现一个!** @return*/public static double PV(double rate, double nper, double pmt, double fv, double type) {/*** 如果年化收益率为零 , monthRate作分母会出现NaN错误,需要对年利率为零进行特殊处理*/if (rate == 0) {return nper * pmt;}double result = -(fv pmt*(1(rate / 12)*type)*((Math.pow(1(rate / 12), nper)-1)/(rate / 12)))/Math.pow(1(rate / 12), nper);return new BigDecimal(result).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();}// FV(rate,nper,pmt,pv , type)/***参考:https://support.microsoft.com/zh-cn/office/fv-函数-2eef9f44-a084-4c61-bdd8-4fe4bb1b71b3** FV 是一个财务函数,用于根据固定利率计算投资的未来值 。*可以将 FV 与定期付款、固定付款或一次付清总额付款结合使用 。** @param Rate必需 。各期利率 。年利率,月利率=年利率/12* @param Nper必需 。年金的付款总期数 。* @param Pmt必需 。各期所应支付的金额 , 在整个年金期间保持不变 。通常 pmt 包括本金和利息,但不包括其他费用或税款 。如果省略 pmt,则必须包括 pv 参数 。* @param pv可选 。现值,或一系列未来付款的当前值的累积和 。如果省略 pv,则假定其值为 0(零) , 并且必须包括 pmt 参数 。* @param type可选 。数字 0 或 1,用以指定各期的付款时间是在期初-1还是期末-0 。如果省略 type,则假定其值为 0 。** PS: pmt与fv至少出现一个!** @return*/public static double FV(double rate, double nper, double pmt, double pv, double type) {/*** 如果年化收益率为零,monthRate作分母会出现NaN错误,需要对年利率为零进行特殊处理*/if (rate == 0) {return nper * pmt;}// "1(rate / 12)"的nper次幂BigDecimal powers = new BigDecimal(Math.pow(1(rate / 12), nper));double fv = -1*(pv*powers.doubleValue() pmt*(1(rate / 12)*type)*((powers.doubleValue()-1)/(rate / 12)));return new BigDecimal(fv).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();}public static void main(String[] args) {// 结果:PV:597771.46System.out.println("PV:" PV(0.08, 240, -5000,0,0));// FV:2581.4System.out.println("FV:" FV(0.06, 10, -200,-500,1));// 要在 18 年以后有一笔 ¥500,000 的年金,每月需存入金额 。// pmt:1290.81System.out.println("pmt:" PMT(0.06, 18*12, 0,-500000,0));// 指定参数条件下贷款的月支付额,不包括支付期限在期初的支付额 。// pmt:10301.64System.out.println("pmt:" PMT(0.08, 10, -100000,0,1));}
如有优化的地方,敬请指点!

相关经验推荐