题目
题目描述
当一个人从银行贷款后,在一段时间内他(她)将不得不每月偿还固定的分期付款。这个问题要求计算出贷款者向银行支付的利率。假设利率按月累计。
输入格式
三个用空格隔开的正整数。
第一个整数表示贷款的原值 w 0 w_0 w0,第二个整数表示每月支付的分期付款金额 w w w,第三个整数表示分期付款还清贷款所需的总月数 m m m。
输出格式
一个实数,表示该贷款的月利率(用百分数表示),四舍五入精确到 0.1 % 0.1\% 0.1%。
数据保证答案不超过 300.0 % 300.0\% 300.0%。
样例 #1
样例输入 #1
1000 100 12
样例输出 #1
2.9
思路
月利率是指按照每个月实时本金而产生,不是按照第一次。由于每月都会还款,因此公式是不太好写出来的。暴力遍历由于这里精确到的是0.1,也就是说从要以0.1为步长从0.1遍历到300,并且加上还要验证该解是否可行。这样产生的计算量较大。
因此采用二分法是较好做法。需要注意的是题目中说精确到0.1是因为无法计算出准确值。程序模拟给出的样例结果是-1.92878
有可能是计算机二进制存储导致数据丢失或者其他原因。总之这里模拟还钱后即使是正确的利率最终金额也不是0,以下是一开始的没通过的代码
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
double w1,w,m;
double l=0,r=300,mid,money=-1;
cin>>w1>>w>>m;
int count=0;
while(money!=0){
mid=(r+l)/2;
money=w1;
for(int i=0;i<m;i++) //模拟还钱
money=money-w+money*(mid/100);
if(money<0){
l=mid;
}
else if(money>0){
r=mid;
}
}
printf("%.1f",mid);
}
由于是近似解,一直卡着一个数
这里采用的是一个笨办法:如果利率卡一个数超过一定次数就认为这个数是近似解。当然解决方法不止这一种,也可以从while循环条件等方面入手。
代码
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
double w1,w,m;
double l=0,r=300,mid,money=-1,lastmid;
cin>>w1>>w>>m;
int count=0;
while(money!=0){
mid=(r+l)/2;
money=w1;
for(int i=0;i<m;i++) //模拟还钱
money=money-w+money*(mid/100);
if(money<0){ //多了说明利率太低
l=mid;
}
else if(money>0){ //还少了说明利率太高
r=mid;
}
if(mid==lastmid){
count++;
}
else{
count=0;
lastmid=mid;
}
if(count==5) //如果利率卡一个数超过5次,说明这个是近似解
break;
}
printf("%.1f",mid);
}