有同学问我,说通货膨胀率这么高,是不是贷款买房很划算,我这边先上结论,再上代码。
_(:з」∠)_,这边同学给的设定,是通货膨胀率6%,每年存款4000,或者还房贷4000,房贷利率多少时,这俩玩意才一样划算?答案是15.25%。
这东西乍一听听容易算,但是真的动手算,还蛮头大的。大家可以直接看代码,我注释很全,不做文字赘述了。
package main.java; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; /* * 问题1:年通货膨胀率6%,是否意味着,你前一年的钱,在今年价值为94%? * 问题2:是否每年叠加? * 问题3:假设你每月4000用于存款or还房贷,房贷还20年,年通货膨胀率6%,房贷利率多少的情况下,房贷比存放着任由通货膨胀贬值划算? * */ public class Main { public static void main(String[] args) { System.out.println("代码开始。\n"); // 月份,4年就是240个月。 int monthes = 240; // 通货膨胀率,6%,也即0.06。 BigDecimal inflation = new BigDecimal("0.06");; // 每月要还的金额,4000元。 int annualPay = 4000; // 利率上限,设为100%,也就是1。 BigDecimal interestUp = new BigDecimal("1"); // 利率下限,设为0%,也就是0。 BigDecimal interestDown = new BigDecimal("0"); // 利率,利率=(利率上限+利率下限)/ 2,接下来用二分法找最合适的利率。 BigDecimal interestRate = interestUp.subtract(interestDown).divide(new BigDecimal("2"), 10, RoundingMode.HALF_UP); // 二分法终止条件,这里只要金额相差1元以内,就认为找到近似解。 BigDecimal tolerantDifference = new BigDecimal("1"); // 要增加利率的标志。 boolean addTheInterestFlag = true; // 存款20年,最终的钱。 BigDecimal moneyDeposit = new BigDecimal(annualPay * monthes); /* 这里想算出,现在我贷款多大价值的房产,等于二十年后的存款。过程中会解决通货膨胀比例问题哦。 */ BigDecimal moneyHouseInitiate = new BigDecimal(1); moneyHouseInitiate = moneyHouseInitiate.divide(inflation.add(BigDecimal.ONE), 10, RoundingMode.HALF_UP); System.out.println("问题1,去年我有Y元,房价Z元,我能买Y/Z的房子;今年房价1.06×Z元,我能买Y/(1.06×Z)的房子。以房子" + "作为参考系,金钱贬值为(Y/(1.06×Z)) / (Y/Z) = 1/1.06 , 约等于:" + moneyHouseInitiate.multiply(new BigDecimal("100")) + "%,"); moneyHouseInitiate = moneyHouseInitiate.pow(20).multiply(moneyDeposit); System.out.println("存款20年,最终的钱是:" + moneyDeposit + "元。"); System.out.println("这里算出今天" + moneyHouseInitiate.intValue() + "元的房子,等于20年后" + moneyDeposit + "的存款。\n"); System.out.println("问题2,当然是叠加的啦。\n"); /* 不幸的是,我的智商没有算出解析解,只能算出数值解,猛男落泪o(╥﹏╥)o * 假设房子全部靠贷款,每月要还4000元。 * 设f(x)为第x个月还剩贷款本金,y为利率,能推出f(x)=(4000 + f(x+1)) / (1+y)。我能循环地求数值解,但是我没办法推导出解析解的公司呀。 * 所以只好用二分法,假设最大利率、最小利率、停止条件,然后不停地试验,直到满足要求。 * */ while (true) { /* 先建好所有月份的列表,后面就可以直接用啦。 */ List<BigDecimal> debt = new ArrayList<>(); for (int i = 0; i < monthes; i++) { BigDecimal bigDecimal = new BigDecimal("0"); debt.add(bigDecimal); } // 先把分母1+y求出来,后面就直接除了。 BigDecimal bigDecimalBottom = new BigDecimal("1"); bigDecimalBottom = bigDecimalBottom.add(interestRate); /* 遍历每个月份,从最后一个月开始计算,循环地求出每个月的剩余贷款。 */ for (int i = monthes - 2; i >= 0; i--) { BigDecimal bigDecimalTop = new BigDecimal(annualPay); bigDecimalTop = bigDecimalTop.add(debt.get(i + 1)); bigDecimalTop = bigDecimalTop.divide(bigDecimalBottom, 10, RoundingMode.HALF_UP); debt.set(i, bigDecimalTop); } /* 显示每次二分法的关键数据。测试时很好用哦。 */ // System.out.println("利率是:" + interestRate); // System.out.println("利率上限是:" + interestUp); // System.out.println("利率下限是:" + interestDown); // System.out.println("本金是:" + debt.get(0).toString()); // System.out.println(); // 求出当前利率的初始贷款,和目标贷款的差值。 BigDecimal difference = debt.get(0).subtract(moneyHouseInitiate); addTheInterestFlag = difference.signum() > 0; difference = difference.abs(); // 差值小于设定,就结束。 if (difference.compareTo(tolerantDifference) < 0) { // 月利率转化为年利率,然后转化成百分比。 System.out.println("问题3,算出来啦,"); System.out.println("利率是:" + interestRate.multiply(new BigDecimal("1200")).divide(BigDecimal.ONE, 2, RoundingMode.HALF_UP) + "%。"); System.out.println("贷款金额是:" + debt.get(0).intValue() + "元。\n"); System.out.println(); break; } /* 二分法,利率大了就把上限调为当前利率,否则把下限调为当前利率 */ if (addTheInterestFlag) { interestDown = interestRate; } else { interestUp = interestRate; } // 新的利率 =(利率上限+利率下限)/ 2 interestRate = interestUp.add(interestDown).divide(new BigDecimal("2"), 10, RoundingMode.HALF_UP); } System.out.println("代码结束。"); } }
代码的运行结果:
问题1,去年我有Y元,房价Z元,我能买Y/Z的房子;今年房价1.06×Z元,我能买Y/(1.06×Z)的房子。以房子作为参考系,金钱贬值为(Y/(1.06×Z)) / (Y/Z) = 1/1.06 , 约等于:94.3396226400%,
存款20年,最终的钱是:960000元。
这里算出今天299332元的房子,等于20年后960000的存款。
问题2,当然是叠加的啦。
问题3,算出来啦,
利率是:15.25%。
贷款金额是:299332元。