众所周知,现在银行的分期贷款利率是很有诱惑性人。表面看利率是很低的,例如招行的闪电贷有时给我的利率是4.3%

但是,由于贷款是分期还本的,我手上的本金每月都在减少,到最后一个月时手上只有少量本金,但是还的利息却还是跟第一个月一样。

  excel提供了一个公式叫irr,专门用来计算这种分期贷款实际利率的。

irr函数有两个参数,第一个是现金流,第二个是预估值。只要我们根据贷款情况填好总贷款金额和每月还款金额就可以算出每月的内部收益率。

月内部收益率*12就是我们的实际贷款利率。预估值一般不用填,只有irr计算失败返回#NUM!才要考虑填,具体可见office官方说明。

  https://support.office.com/zh-cn/article/IRR-%E5%87%BD%E6%95%B0-64925eaa-9988-495b-b290-3ad0c163c1bc

  为方便计算,我做了一个excel表格,有兴趣大家可以去下载。只要输入下面图片黄底黑体列,即可自动得出折算年利率。招行的闪电贷利率表面看是4.3%,实际年化利率是7.84%。

  如果你把钱投理财产品,没有7.84%以上你实际是亏本的。

  当然,本文重点不是介绍irr函数,而是我写(抄)的一个计算irr的程序(函数)。使用的是二分迭代法(网上看还有牛顿迭代法和加速迭代法,这两种需要用到数学知识)

之所以用c语言写一个,原因是我们最近项目组有一个c程序需要计算内部收益率。我从网上找了一个程序改了一下,变成一个函数,并加上注释,方便理解和调用。

  程序和代码还有前面提到的表格我都已经上传,有需要可以去下载。实现代码如下:

// testirr.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <math.h>//const double zero = 1e-5;//int n;/*
//代码是在csdn上找到的 我拿下来改了一下
//https://blog.csdn.net/dinghaoseu/article/details/50322117
//这是原来的代码
double quickpow(double a, int b)
{double ans = 1;while(b){if(b & 1) ans = ans * a;a = a * a;b >>= 1;}return ans;
}double makeans(double irr)
{double ans = 0;for(int i = 1; i <= n; i++)ans += ( a[i] / (quickpow(1 + irr, i)) );return ans;
}
*/
//计算流出Npv
double getNpvOut(double irr, const double arrOutMoney[], int n)
{double npv = 0;double denominator = 1 + irr; //分母double multiplier = denominator; //乘数for (int i = 1; i <= n; ++i){npv += arrOutMoney[i] / denominator; //即:arrOutMoney[i] / (quickpow(1 + irr, i)denominator *= multiplier;}return npv;
}//最小最大IRR(内部收益率) 用于折算年化率计算
//最小值必须大于-1 最大值1其实就足够了,折算成年化收益率是120%(国家规定利率不能超过30%)
//数字越小计算速度越快,为保险计这里填10
#define IRR_MIN -1.0f
#define IRR_MAX 10.0f//二分迭代寻找合适的irr值(如果存在多个irr,取第一次找到的值,不保证大小顺序)
//arrInOutMoney是分期现金流 nArrLen是arrInOutMoney元素个数
//arrInOutMoney[0]必须是负数,代表总分期金额(负数),后面是每期还款金额(正数)
//返回[IRR_MIN, IRR_MAX]之间的数字代表符合要求的IRR值,<IRR_MIN代表找不到合适的IRR
double binarySearchGetIrr(const double arrInOutMoney[], int nArrLen)
{double l = IRR_MIN, r = IRR_MAX; //irr取值-1~10之间 int n = nArrLen - 1;//int nCnt = 0;while (l < r){//每次从最大和最小期望IRR中间取一个数值进行npv测算double mid = (l + r) / 2;//现在是用除法求Npv,其实可以改成用乘法求,效率会高一点//因为计算机处理乘法速度比较快double npvOut = getNpvOut(mid, arrInOutMoney, n);//++nCnt;//如果结果等于0说明找到符合要求的IRRif (fabs(npvOut + arrInOutMoney[0]) <= 1e-5) //double类型不能直接与0比较判断是否相等
        {    //printf("nCnt = %d\n", nCnt); //经测试,一般分12期迭代次数在30~60之间return mid;}//irr越大,npvOut越小,故npvOut太大时irr就应该落在mid和r之间,反之则反之else if (npvOut > -arrInOutMoney[0]) {l = mid;}else{r = mid;}}//printf("nCnt = %d\n", nCnt);//找不到返回比IRR_MIN还小的值return IRR_MIN - 1;
}//输入按月分期现金流,输出对应irr和折算年化收益率
//arrInOutMoney是分期现金流 nArrLen是arrInOutMoney元素个数(一般是7或者13)
//arrInOutMoney[0]必须是负数,代表总分期金额,后面是每期还款金额(正数)
//nCheckFlag = 0,代表直接计算irr,否则会先对数据合法性做检查
//返回0代表成功 其它代表失败 失败原因存放在errBuf(调用者需要保证至少有256个字节空间)
int GetIrrAndAnnualizedRate(const double arrInOutMoney[], int nArrLen,OUT double *pIrr, OUT double *pAnnualizedRate, int nCheckFlag, OUT char *errBuf)
{double irr = 0;if (nCheckFlag != 0){double inMoney, outMoney;int i;if (arrInOutMoney == NULL || nArrLen < 2){strcpy(errBuf, "arrInOutMoney需要非空并且元素个数大于2个");return -10;}inMoney = arrInOutMoney[0];outMoney = 0;for (i = 1; i < nArrLen; ++i){if (arrInOutMoney[i] < 0){//不支持多次现金流入(因为没这个需求,不要浪费计算力)outMoney = -1;break;}outMoney += arrInOutMoney[i];}if (inMoney >= 0 || (-inMoney > outMoney)){strcpy(errBuf, "第一个元素必须是负现金流,之后每个元素均是正现金流,""并且正现金流之和要大于负现金流");return -20;}}irr = binarySearchGetIrr(arrInOutMoney, nArrLen);if (irr < IRR_MIN){sprintf(errBuf, "%.5f(%.2f%%)~%.5f(%.2f%%)之间无法找到合适的irr,请检查现金流是否输入异常",IRR_MIN, IRR_MIN * 12 * 100, IRR_MAX, IRR_MAX * 12 * 100);return -30;}*pIrr = irr;*pAnnualizedRate = irr * 12 * 100;return 0;
}int getIrrDemo()
{double irr, annualizedRate;double a[100 * 12 + 1];int n, nRet;char errBuf[256];printf("**************如果要退出,请在还款期数填0**************\n");while ((printf("input 还款期数 n(0代表退出):")) && ~scanf("%d", &n) && n){printf("n = %d\n", n);if (n >= sizeof(a) / sizeof(a[0])){printf("n值太大,不支持\n");continue;}printf("输入分期金额(负数):");if (scanf("%lf", &a[0]) != 1) {printf("输入的金额不能包含非数字和小数点\n");getchar();continue;}printf("输入%d期还款金额(正数),每输入一期按一次回车:", n);for (int i = 1; i <= n; i++){scanf("%lf", &a[i]);}nRet = GetIrrAndAnnualizedRate(a, n + 1, &irr, &annualizedRate, 1, errBuf);if (nRet != 0){printf("error:[%s]\n", errBuf);continue;}//计算irr常用的方法是迭代计算,即不断尝试可能值,根据尝试结果缩小范围,直到找到符合要求的值//网上能找到的迭代算法有二分迭代,牛顿迭代,加速迭代,其中二分迭代最好理解,最容易开发irr = binarySearchGetIrr(a, n + 1);if (irr < IRR_MIN){printf("找不到合适的irr\n");}else{printf("irr = %.6f  年化收益率(12 * irr) = %.4f%%\n", irr, annualizedRate);}}return 0;
}int main(int argc, char *argv[])
{getIrrDemo();//system("pause");return 0;
}

  

  

转载于:https://www.cnblogs.com/kingstarer/p/10322343.html

使用c语言计算分期贷款折算年化收益率(内部收益率IRR*12)相关推荐

  1. 语言计算:信息科学技术中长期发展的战略制高点

    语言计算:信息科学技术中长期发展的战略制高点 (2010-10-10 17:31:25) 标签: 校园 分类: 工作篇 自然语言处理,简单地说,就是用计算机来处理人类的语言(英文.中文等).由于语言是 ...

  2. python计算利率贷款_python 贷款利息计算公式

    固定支付贷款 固定支付贷款(fixed-payment loan) 也称为分期偿还贷款(fully amortized loan). 贷款人向借款人提供一定数量的资金,在约定的若干年度内,借款人每个期 ...

  3. C++ 编程基础练习——贴现分期贷款问题

    C++ 贴现分期贷款问题 客户贷款的发放不总是那么直接.有一种形式的贷款叫做贴现分期货款,具体实施方法如下:假设某笔贷款的面值为1000美元,利率为15%,货款期限为18个月.那么年利息为面值1000 ...

  4. 用数据分析计算分期消费利率

    导语 大家都知道一线城市生活压力大,年轻人如果没有家里人的帮助想要独立扎根并非易事.好不容易凑足了首付买了房,还要每月透支的还着房贷,在资金链不足的情况下想要得到其他方面的物质满足那就只能借钱了. 我 ...

  5. 汉诺塔怎么加计数次数c语言,C语言计算汉诺塔最小移动步数 (二)

    前几天写的:C语言计算汉诺塔最小移动步数(一) 当时还不知道用2^n-1这个公式来求解汉诺塔移动步骤.=_= 偶然间在网上发现了这个公式,发现当时写的算法还是比较繁琐的.所以又根据这个公式又写了一个. ...

  6. R语言计算曼哈顿距离(Manhattan Distance)实战:计算两个向量的曼哈顿距离、dist函数计算矩阵中两两元素的曼哈顿距离

    R语言计算曼哈顿距离(Manhattan Distance)实战:计算两个向量的曼哈顿距离.dist函数计算矩阵中两两元素的曼哈顿距离 目录 R语言计算曼哈顿距离(Manhattan Distance ...

  7. R语言计算杰卡德相似系数(Jaccard Similarity)实战:自定义函数计算Jaccard相似度、对字符串向量计算Jaccard相似度、将Jaccard相似度转化为Jaccard距离

    R语言计算杰卡德相似系数(Jaccard Similarity)实战:自定义函数计算Jaccard相似度.对字符串向量计算Jaccard相似度.将Jaccard相似度转化为Jaccard距离 目录 R ...

  8. R语言计算平均值的标准误差(standard error of the mean):自定义函数计算平均值的标准误差、使用plotrix包的std.error函数计算平均值的标准误差

    R语言计算平均值的标准误差(standard error of the mean):自定义函数计算平均值的标准误差.使用plotrix包的std.error函数计算平均值的标准误差 目录

  9. R语言计算回归模型每个样本(观察、observation、sample)的DFFITS度量实战:忽略单个观察(样本)时,回归模型所做的预测会发生多大的变化

    R语言计算回归模型每个样本(观察.observation.sample)的DFFITS度量实战:忽略单个观察(样本)时,回归模型所做的预测会发生多大的变化 目录

最新文章

  1. numpy permutation排列组合方法
  2. Oracle 快速插入1000万条数据的实现方式
  3. standard python venv module_python 在venv中报错 ModuleNotFoundError: No module named 'MySQLdb'
  4. Oracle11g新特性注意事项
  5. LQ训练营(C++)学习笔记_深度优先搜索
  6. 8、angular的select
  7. 浅谈C++容器(转)
  8. 微信语音遥控Windows Azure云虚拟机
  9. Oracle 中取当前日期的上个月最后天和第一天
  10. 用户控件中图片路径问题(用户控件、图片路径) ,ResolveUrl
  11. python列表的嵌套_Python 展开多层嵌套的列表
  12. Exporting the operator hardsigmoid to ONNX opset version 11 is not supported
  13. 报考软件资格考试过程详解--附学习分享
  14. 码元、符号、波特率、比特率等概念的了解
  15. 交换机和路由器的基本配置
  16. 襄阳教育云平台实名认证_襄阳教育云平台学生空间官网-优教信使襄阳教育云平台下载V4.1.6-西西软件下载...
  17. 资讯App排行榜出炉,凤凰新闻客户端如何成了行业变量?
  18. QT--在注释中遇到意外的文件结束
  19. 上传图片方向不对 php,如何解决IOS中html5上传图片方向问题?
  20. 出海的成本越来越高,奈何

热门文章

  1. 基于vivado DDS ip核的DDS信号发生器(可调频调相)
  2. matlab 函数句柄@的介绍_什么是函数句柄(转)
  3. 【NI Multisim 14.0原理图设计基础——元器件分类】
  4. [CF1336F]Journey
  5. 【开发教程11】疯壳·开源蓝牙心率防水运动手环-整机功能代码讲解
  6. 小鱼鱼的 Python 学习笔记(第一周)
  7. 【U8】U8.11(8.12) access版本如何升级到用友T3及U8
  8. microbit测试题
  9. Sensor Hub
  10. 洛谷 P3389 【模板】高斯消元法 × 洛谷 P2455 [SDOI2006]线性方程组