《入门经典》——6.25
非线性方程求根:
一次向银行借a元钱,分b月还清。如果需要每月还c元,月利率是多少(按复利计算)?例如借2000元,分4个月还每月510元,则月利率为0.797%。答案不应超过100%。
分析:首先我们先从数学的角度来理解题意,需要注意的是,这里所谓复利的意思应该是指每个月涨息之后然后还贷,这样是非常便利我们列出计算方程的。
以样例为例,我们可以列入如下的方程,设利率是x:
(((2000(1+x)-c)(1+x)-c)(1+x)-c)(1+x)-c = 0.
可以看到这是一个非线性方程,而且对于不同的月数b,这个方程左边的长度还会不同,因此我们应该果断放弃从函数的角度来求解这个方程的根。
结合简单的函数知识,我们知道函数零点-方程根是通解的,因此我们可以将根视为函数f(a,b,c,rate)的零点,然后在区间[0,100]枚举rate来求得这个方程的零点。
非常需要注意的是,在利用二分求零点的时候,非常有必要分析一下函数自身的单调性,因为这将直接影响根据计算结果继续二分区间,而结合这道题目,容易看到函数是单调递增的。
简单的参考代码如下:
#include<iostream> #include<cstdio> using namespace std; double f(double money,int month , double monthlyment,double rate) { while(month--) { money = money*(1+rate/100.0); money -= monthlyment; } return money; } int main() { double money , monthlypayment , rate; int month; printf("Input money,month,monthlypayment:\n"); scanf("%lf %d %lf",&money,&month,&monthlypayment); double hi , lo; hi = 100.0 , lo = 0.0; while(hi - lo > 1e-5) { double mid = (hi + lo)/2.0; // printf("%lf",mid); if(f(money,month,monthlypayment,mid) > 0) hi = mid; else lo = mid; } printf("rate(monthly) : %.3lf%%\n",lo); }