求一“银行存款最优解”的算法

房梁之鼠 2008-01-07 10:32:59
假设银行整存整取存款不同期限的月息利率分别为:
0.63% 期限=1年
0.66% 期限=2年
0.69% 期限=3年
0.75% 期限=5年
0.84% 期限=8年
利息=本金*月息利率*12*存款年限。
现在某人手中有2000元钱,请通过计算选择一种存钱方案,使得钱存入银行20年后得到的利息最多(假定银行对超过存款期限的那一部分时间不付利息)。
------------------------------------
我嵌套了5个for 循环,得出了124种方案,其中最大利息方法是 年限为一年的存1年,年限为三年的存1年,年限为八年的存2年,最大利息为3260.84
但是问题在与先存一年的,再存三年的,然后存八年的 和 先存八年的,再存一年的,然后存三年的,得到的结果肯定不等,
如果在这124种方案中再做组合,然后求出最大利息,因该没错。但是这样做起来很烦。有没有简单点的方法来实现这个程序的功能。请高手指教。

...全文
1738 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tiger_Zhao 2008-01-08
  • 打赏
  • 举报
回复
复利的计算公式
期末的:本金+利息=本金*(1+D)^n
其中n为结算次数,D为每次结算的利率。

而题中
>利息=本金*月息利率*12*存款年限
=本金*(C-1)
这就是说,在存款年限n中不是按复利计算的,为了全部转统一到按年的复利计算,需要有
C=D^n
所以D就是对C开n次根。

由于:本金+利息=本金*(1+D1)^n1*(1+D1)^n1*...*(1+Dk)^nk
并且满足:n1+n2+...+nk=20
为了使得获利最大,必须要尽量选取最大的D1、D2、...、Dk
简单规划后就是4个5年期存款

yaoyuantk 2008-01-07
  • 打赏
  • 举报
回复
太多的for 循环了!
chlaws 2008-01-07
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{
int corpus=2000; //本金
int A,B,C,D,E; //对应年份个数
int a,b,c,d,e;
int Ayear=1,Byear=2,Cyear=3,Dyear=5,Eyear=8;
int sum = 20;
double accrual;//利息
double MAX_accrual=0;//最大利息
double Ainterest= 0.0063,Binterest= 0.0066,Cinterest= 0.0069; //个年份利率
double Dinterest= 0.0075,Einterest= 0.0084;
printf("\n**************\n");
for(A = 0 ;A<=20; A++)
{
for(B = 0; B<=10; B++)
{
for(C = 0; C<7; C++)
{
for(D = 0; D<=4; D++)
{
for(E = 0 ; E<3; E++)
{
if((Ayear*A) + (Byear*B) + (Cyear*C)+(Dyear*D) + (Eyear*E) == sum)
{
accrual=corpus*12*(Ayear*A*Ainterest+Byear*B*Binterest+
Cyear*C*Cinterest+Dyear*D*Dinterest+Eyear*E*Einterest);
if(MAX_accrual < accrual)
{
MAX_accrual = accrual;
printf("\n**************\n");
printf("A = %d\t B = %d\t C = %d\t D = %d\t E = %d\t",A,B,C,D,E);
printf("\nMAX_accrual = %lf\n",MAX_accrual);
a=A; b=B;c=C;d=D;e=E;
}
}
}//for e
}//for d
}//for c
}//for b
}//for a
printf("存%d个1年\t 存%d个2年\t 存%d个3年\t 存%d个5年\t 存%d个8年\t",a,b,c,d,e);
printf("\nMAX_accrual = %lf\n",MAX_accrual);
getch();
}


kojie_chen 2008-01-07
  • 打赏
  • 举报
回复
难道是线性规划的题目?..
ltc_mouse 2008-01-07
  • 打赏
  • 举报
回复
感觉这种问题最好结合数学方法,从理论上证明某种方案优于其他方案,然后再用编程探试,或者说编程验证。

PS: 楼主4楼给出的程序不太对吧,可能是手误,年限跟问题中的年限不符,呵呵~ 估价函数f的计算,好像忽略了利息也能增殖的问题。如果就是那样计算,跟先存几年期、后存几年期没有关系了。
另外,从程序角度,有优化的余地,假设用xi表示i年期的期数,除了Sum{xi}=20外,还有明显的约束条件0<=xi<=[20/i]
房梁之鼠 2008-01-07
  • 打赏
  • 举报
回复
不知道是不是我对题的理解有误~~
假如是在银行存4年一年期限的,然后存2年八年期限的。
和先存2年八年期限的,然后存4年一年期限的,
所得到的利息会一样么。
也就是说,在第二次及以后存款的时候,本金是不要加上原来的2000本金+上次存款得到的利息。
房梁之鼠 2008-01-07
  • 打赏
  • 举报
回复

To: goodluckyxl
你的意思是这样么?
得到f的最大值就是要求的方案,对么?

for(x1 = 0; x1<= 20; x1++)
{
for(x2 = 0; x2<= 20; x2++)
{
for(x3 = 0; x3<= 20; x3++)
{
for(x4 = 0; x4<= 20; x4++)
{
for(x5 = 0; x5<= 20; x5++)
{
if(x1+ x2*2 + x3*3 + x4*4 + x5*5 == 20)
{
f = 0.63*x1 + 0.66*x2 + 0.69*x3 + 0.75*x4 + 0.84*x5;
}
}
}
}
}
}


goodluckyxl 2008-01-07
  • 打赏
  • 举报
回复
整个计算方法思路基本就是这样
可能计算利息有更复杂的方法但是同样合并考虑后公式是差不多的
f = (1+0.63*x1)*m+(1+0.63*x1)*m*(1+0.66*x2)....
不过这样叠加后稍微复杂了一些
变成高次方程求解了
需要采用一些高次求解过程了
我真是学忘了 只记得高等代数有一章讲了高次方程求解
goodluckyxl 2008-01-07
  • 打赏
  • 举报
回复
以前数学建模时这个是最基本的题目
现在真是时间太长忘记了
f = 0.63*x1+0.66*x2+0.69*x3+0.75*x4+0.84*x5 或者一个max
其中具有一些限制条件
xi属于非负整数
x1+x2+x3+x4+x5=20
这类求解查查建模书 肯定是有类是方法公式的
推导出来进行程序计算
chlaws 2008-01-07
  • 打赏
  • 举报
回复
给楼主说一点.
整存整取的概念你还不清楚吧
银行整存整取是按年理息算的
杨文 2008-01-07
  • 打赏
  • 举报
回复
用不着那么大费周张吧!不过还是UP一下啊!我没时间给你一个更简单的了,是用C语言实现的!
chlaws 2008-01-07
  • 打赏
  • 举报
回复
对18楼的中的D表示不理解.
不知怎么得到的?
「已注销」 2008-01-07
  • 打赏
  • 举报
回复
强帖 上周和同学没事算体彩7位数每级中奖概率
搞了4个小时......

我个人认为此贴应该想象几个极端数据,然后按常理推断,类似Tiger——Zhao的方法
房梁之鼠 2008-01-07
  • 打赏
  • 举报
回复
虽然不理解Tiger_Zhao 的解法。
但是特地证明了下,好像就是这个样子。


float ben = 2000.00f;
float xi = 0.0f;

for(int i = 1; i<= 4; i++)
{
xi = ben*0.0075*12*5;
ben = ben+xi;
printf("存款第%d次后利息:%lf, 本金为:%lf\n",i,xi,ben);
}
printf("最终的利息为:%lf\n",ben-2000);

存款第1次后利息:900.000000, 本金为:2900.000000
存款第2次后利息:1305.000000, 本金为:4205.000000
存款第3次后利息:1892.250000, 本金为:6097.250000
存款第4次后利息:2743.762451, 本金为:8841.012695
最终的利息为:6841.012695
ltc_mouse 2008-01-07
  • 打赏
  • 举报
回复
Tiger_Zhao给出了很漂亮的解法,:-)
房梁之鼠 2008-01-07
  • 打赏
  • 举报
回复

if((Ayear*A) + (Byear*B) + (Cyear*C)+(Dyear*D) + (Eyear*E) == sum)
{
corpus = 2000;
accrual=corpus*12*Ayear*A*Ainterest;
corpus += accrual;
accrual=corpus*12*Byear*B*Binterest;
corpus += accrual;
accrual=corpus*12*Cyear*C*Cinterest;
corpus += accrual;
accrual=corpus*12*Dyear*D*Dinterest;
corpus += accrual;
accrual=corpus*12*Eyear*E*Einterest; //如果E 为0 , 即:accrual==0
if(MAX_accrual < accrual) //则这步比较无意义
{
MAX_accrual = accrual;
printf("\n**************\n");
printf("A = %d\t B = %d\t C = %d\t D = %d\t E = %d\t",A,B,C,D,E);
printf("\nMAX_accrual = %lf\n",MAX_accrual);
a=A; b=B;c=C;d=D;e=E;
}
}

Tiger_Zhao 2008-01-07
  • 打赏
  • 举报
回复

A n C D
----- - ------ -----------
0.63% 1 1.0756 1.075600000
0.66% 2 1.1584 1.076289924
0.69% 3 1.2484 1.076757536
0.75% 5 1.4500 1.077143588
0.84% 8 1.8064 1.076717423
----- - ------ -----------
A ;月息利率
n ;存款期限
C=1 + A*12*n ;存款期限结束后 (本金+利息)/本金 的比率
C=D^n ;该存款期限内的年(复利)利率

选最大可能的D进行存款,正好为4个5年期存款
最终获利
=2000*(1.45)^4-2000
=6841.0125

注:^为指数运算,D^n 等于 pow(D, n)

chlaws 2008-01-07
  • 打赏
  • 举报
回复

//特地证明了下.
//以下数值都按取整算;
按顺序存储: 1 . 3. 8
1年 年息:151
3年 年息:534
2个8年后年息:4331

按顺序存储: 8 .1. 3
2个8年年息:3225.6
1年 年息:243
3年 年息:861
总年息:4331
得到结论:
年息的多少跟存储的顺序无关


PS:不知上面野地里的人说的12楼的程序错在哪.偶自己米发现.
因为是穷举算法.跟存不存8年米什么关系.只要满足年份是20就行了.

ltc_mouse 2008-01-07
  • 打赏
  • 举报
回复
小江12楼给出的求利息那段代码,似乎还是不对。如果不存8年期的,貌似所有利息都泡汤了,^_^
另外,连续存n期的m年期,按这种算法,这段时间只能拿到本金的利息~ 没有滚利,:) 个人觉得应该用等比数列求和

尝试证明了下,跟先后存几年期的顺序没有关系的。如下,不知道对不对:
设rate[i]{i=1,2,3,5,8}表示i年期的利息率。
有m年期和n年期的m+n年存款方案,则按照m在前和n在前,可得到利息分别为:
先存m年期:rate[m]*m*12 + (1+rate[m]*m*12)*rate[n]*n*12
先存n前期: rate[n]*n*12 + (1+rate[n]*n*12)*rate[m]*m*12
这两个表达式是等价的,因而两期的存款,交换顺序不影响利息收益。
而所有元素相同的两个排列,一个排列可以通过两个元素间的两两交换变换到另一个排列。

最后这句排列的置换,有理论基础吗?忘记了,不是很肯定...如果错了,上述证明就无效了....
diaoxue 2008-01-07
  • 打赏
  • 举报
回复
在Lindo或Lingo里做
加载更多回复(5)
目 录 1、需求与功能分析 (3) 2、系统总体框架 (4) 3、模块设计与分析 (5) 4、类的设计与分析 (7) 5、特色算法分析 (9) 6、功能测试 (10) 7、存在的不足与对策 (15) 8、程序源代码 (16) 需求与功能分析 随着社会经济的发展,信息化程度的不断深入,银行的传统业务己愈来愈不能满足银 行客户的需要。 现今,人们的金融意识、科技意识己经有了很大的提高,在紧张忙碌的生活中,己越 来越来不习惯每月奔忙于各银行营业柜台之问去排队缴各种各样的费用了;同时,各种 经营单位如电信、移动、供电、煤气、自来水、证券等等一是为了提高服务质量、方便 客户,二是为了减轻自己日趋繁重的工作量,纷纷委托银行为其开展代收代付业务:同 时,随着我国加入世贸组织的日益临近,我国的银行业将面临更加激烈的同业竞争,如 何提供更多的金融产品和更优质的服务,如何吸引更多的客户,如何利用计算机技术加 强银行帐户信息管理、进行银行业务再造,提高银行的工作效率和业务竟争能力是摆在 各家银行面前的一个迫切需要解诀的问题。 近几年来,各商业银行加快了与社会各业的合作,利用自身的网点优势和业务特点, 为其提供各种高效、快捷的代收代付业务,也就是中间代理业务,目前以与广大人民群 众生活密切相关的各项缴费业务如水电费、电话费、手机费等代收业务为主,这些业务 开展方式多种多样,但一般都离不开计算机的高效管理支持。 随着代理业务不断发展,业务品种越来越多,各项业务做法互有差异,这就对银行的 电子化水平和相应的管理水平提出了更高的要求。如何利用电子化的手段构建一个高效 统一的、通用灵活的系统来管理各种各样的业务,是每个商业银行所要研究的课题。支 持决策系统的,需要在数据库的基础上,进行联机分析处理,每次处理的数据量大,响 应时间长。 特别是银行每天要处理大量的存取款事件,做好存取款是银行工作重要的环节,然而 要有效处理必须要有良好的程序和数据管理系统来建立一个良好的软件系统来实现快速 、有效、准确、安全的处理银行事物。 主要用于银行的储蓄卡管理系统,它可以帮助我们有效、准确、并且高效实现的完成 存取事件。此系统操作方便效率、安全性高,只要客户开户并设定好密码就可以轻松的 实现存取款。 系统实现的主要有储蓄卡开户管理、存取款管理、用户查询历史数据显示、注销等功 能。 储蓄卡开户管理模块:卡号、姓名、开户金额、身份证号、地址、电话、密码、确认密 码和保存组成。(开户金额必须是数字,密码和确认密码必须一样是六位数字) *查询历史数据模块:存款记录、取款记录、余额显示等。 *注销模块:一旦注销该卡号就不存在且余额提醒你取出。 通过该银行账户管理系统地运行,使办公人员可以轻松快捷的完成对账户管理的任务, 提高账目管理效率,使银行的账目管理工作系统化、规范化、自动化。 该银行帐目管理信息系统,优点是设计过程思路清晰、模块划分简洁,设计各阶段分工 明确。经过实践证明,该划分是合理的,极大得提高了本系统的实现。 系统总体框架 图1 -1 1. 模块设计与分析 储蓄卡开户管理模块: 1. 登录页面 输入卡号和密码,根据用户输入的卡号和密码,到后台文件查询,若正确则登录成功 ,并保存卡好信息已备后用。 若卡号存在和密码不匹配或无该卡号已经注销,提示该卡号已存在或已注销,保持界 面三次不变等待用户的重新输入。 3.2 主界面页面 主要导航栏有:欢迎使用储蓄卡管理(存款、取款、查询余额、查询历史记录、注销 退出) 3.3 储蓄卡开户页面 提供开户界面,由用户输入新储蓄卡的所有信息,将该信息保存到文件中,并将开户 金额作为该卡的第一次存款记录存人文件。 3.4 存钱页面 从登录界面得到卡号,并提供数据输入界面,等待用户的输入存款金额。从后台数据 库中找到该用户余额记录,修改余额,并将该存款事件的相应信息写人数据库,同时将 存钱的金额显示在页面上。 3.5 取款页面 从登录界面得到卡号,并提供数据输入界面,等待用户输入取款金额,如果取款金额 大于该用户卡上的余额则不能取款,或者将新的余额写人文件,并将本次取款事件写入 文件同时将取钱的金额显示在页面上,。 3.6 查询余额页面 从登录界面得到卡好,把该卡上的余额显示到界面中。 3.7 查询历史记录页面 从登录界面得到卡号,把该卡的所有存款取款信息查询出来,并显示在页面上。 3.8 注销页面 从关闭文件,状态为注销,最后关闭整个系统。 列举取款模块进行分析: void Function::Drawing(User &u) { system("cls"); cout<<"\n\n\n\t\t*********************************************\n"<

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧