标题: 还款计算
银行贷款的等额本息还款方法是:
每月还固定的金额,在约定的期数内正好还完(最后一个月可能会有微小的零头出入)。
比如说小明在银行贷款1万元。贷款年化利率为5%,贷款期限为24个月。
则银行会在每个月进行结算:
结算方法是:计算本金在本月产生的利息: 本金 x (年利率/12)
则本月本金结余为:本金 + 利息 - 每月固定还款额
计算结果会四舍五入到“分”。
经计算,此种情况下,固定还款额应为:438.71
这样,第一月结算时的本金余额是:
9602.96
第二个月结算:
9204.26
第三个月结算:
8803.9
….
最后一个月如果仍按固定额还款,则最后仍有0.11元的本金余额,
但如果调整固定还款额为438.72, 则最后一个月会多还了银行0.14元。
银行会选择最后本金结算绝对值最小的情况来设定 每月的固定还款额度。
如果有两种情况最后本金绝对值相同,则选择还款较少的那个方案。
本题的任务是已知年化利率,还款期数,求每月的固定还款额度。
假设小明贷款为1万元,即:初始本金=1万元。
年化利率的单位是百分之多少。
期数的单位为多少个月。
输入为2行,
第一行为一个小数r,表示年率是百分之几.r<30
第二行为一个整数n,表示还款期限。 (6<=n<=120)
要求输出为一个整数,表示每月还款额(单位是:分)
例如:
输入:
4.01
24
程序应该输出:
43429
再比如:
输入:
6.85
36
程序应该输出:
30809
利用二分搜索的思想,先计算出每月还款的上下限,无利息时最少,最后一次还最多,即:
**int left = 1000000 / n;
int right = 1000000 * pow((100 + r)/ 100,n/12) / n;**
其中精确到分,我给虽有数字均扩大100,把问题转换成为整数的二分。
其中关键要对sum取double型因为分之后的小数位四舍五入时会对分位产生影响,
因此: sum = (double)(int)(sum + 0.5);手动四舍五入很关键。
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstdio>
#include<functional>
#define INF 0x3f3f3f3f
using namespace std;
double r, n;
double ans[100];
double temp[100];
int cnt = 0;
int search(int x)
{
double sum = 1000000;
///涉及精度,应该用double型
for (int i = 0;i < n;i++)
{
sum = sum + sum*r / 12 / 100 - x;
///此时应对sum四舍五入!
sum = (double)(int)(sum + 0.5);
}
ans[cnt] = x;
if (x == 30809) cout << sum << endl;
if (x == 30808) cout << sum << endl;
temp[cnt] = sum;
cnt++;
return sum;
}
int main()
{
cin >> r >> n;
int left = 1000000 / n;
int right = 1000000 * pow((100 + r)/ 100,n/12) / n;
int flag = 0;
int mid;
while (right>=left)
{
//mid = (right + left) / 2;
mid = left + (right - left) / 2;
int t=search(mid);
if (t > 0) left = mid+1;
else if (t < 0) right = mid;
else {
flag = 1;
break;
}
if (left == right) break;
}
if (flag) cout << mid;
else {
double a = INF;
int b = 0;
for (int i = 0;i < cnt;i++)
{
if (abs(a) > abs(temp[i]))
{
a = temp[i];
b = i;
}
else if (abs(a) == abs(temp[i]))
{
if (temp[i]>0 && a < 0)
{
a = temp[i];
b = i;
}
}
}
printf("%.0f\n", ans[b]);
}
return 0;
}
也可以不记录所有的结余sum值,只需要比较,mid,mid-1,mid+1三个数的结果即可。如下所示:
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstdio>
#include<functional>
#define INF 0x3f3f3f3f
using namespace std;
/*
有数据不对。。。。。
*/
double r, n;
int search(int x)
{
double sum = 1000000;
for (int i = 0;i < n;i++)
{
sum = sum + sum*r / 12 / 100 - x;
sum = (int)(sum + 0.5);
}
return (int)sum;
}
struct node
{
int x, mid;
};
node ans[5];
bool cmp(node s1, node s2)
{
return abs(s1.x) < abs(s2.x);
}
int main()
{
cin >> r >> n;
int left = 1000000 / n;
int right = 1000000 * pow((100 + r) / 100, n / 12) / n;
int flag = 0;
int mid;
while (right >= left)
{
//mid = (right + left) / 2;
mid = left + (right - left) / 2;
int t = search(mid);
if (t > 0) left = mid + 1;
else if (t < 0) right = mid;
else {
flag = 1;
break;
}
if (left == right) break;
}
ans[0].x = search(mid);ans[0].mid = mid;
ans[1].x = search(mid+1);ans[1].mid = mid+1;
ans[2].x = search(mid-1);ans[2].mid = mid-1;
sort(ans, ans + 3, cmp);
cout << ans[0].mid << endl;
return 0;
}