我和老婆打赌的结果
来源:互联网 发布:商品进销存软件 编辑:程序博客网 时间:2024/04/28 21:40
我们要计算一个滚动投资的结果,需求是这样的:
每点需要200元来购买,每点可以收获26次,每次的收获的金额如下:
第一次10元,第二~第六次20元,第七~第八次30元,第九次38元,第十~第二十六次15元。每半个月收获一次。
滚动投资的意思是,最开始所投资的钱200点,投资日起2006.1.1,那么第一次2006.1.15就收获200*10元(也就是10个点),立即投资,那么到第二次2006.1.30的时候总共获得200*20+200*10/200*10 = 4100元(也就是20点零100元,这一百元因为不够一个点所以留到下次投资)。到2006.2.15所获得的金额200*20+10*20+20*10. 依此类推。
我和老婆打赌,她用Excel表来计算,20分钟,搞定了。每个月的金额,每次的金额,总共投资的金额一目了然。而且可以设定投资的百分比,投资的总金额,开始的时间。很智能。
而我用了她三倍的时间写了一个递归的程序,刚开始执行还好,计算前7个月都没有问题,但是到第8个月左右的时候程序就一直执行了,我仔细一检查发现复杂度太大了,n! ,也就是说在第十次3628800次循环,第十一次就循环次数过亿了,另外因为递归程序局部变量暂用堆栈,所以基本上就不动了。
十分郁闷。
后来我察看了一下递归的资料发现,
要注意一定要留个出口.其它的就要注意一下时间复杂度或空间复杂度,某些算法(比如二叉树的遍历),在规模不大的情况下用递归不但编码方便,而且系统开销不大,但达到一定规模后用递归系统开销就很大了,这时要注意使用非递归的方法了.
而且所有的递归算法理论上都能修改成非递归算法。
所以我又开始修改成非递归的算法,修改成非递归的一般规律是找到循环的规律,用循环代替。
代码如下:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class test {
int a[] = { 10, 20, 20, 20, 20, 20, 20, 30, 30, 38, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
/**
* 计算截止到第times次为止(包括第times次),所投入的全部金额(包括第一次投入的)
* @param times 计算截止到第times次为止(包括第times次)
* @param invest 最开始投入的金额
* @return
*/
public int getAllInvestMoney(int times,int invest){
List list = result(times,invest);
int result = 0 ;
for (Iterator iter = list.iterator(); iter.hasNext();) {
Integer num = (Integer) iter.next();
result+=num.intValue();
}
return result;
}
/**
* 计算在第times次的时候,所能获得的金额.
* @param times 计算截止到第times次为止(包括第times次)
* @param invest 最开始投入的金额
* @return
*/
public int getInvestMoney( int times,int invest){
List list = result(times,invest);
Integer result = (Integer)(list.get( list.size()-1));
return result.intValue();
}
/**
* 显示所有的投资的金额
* @param times
* @param invest
*/
public void showAllInvestInfo( int times,int invest){
List list = result(times,invest);
int j=0;
for (Iterator iter = list.iterator(); iter.hasNext();) {
Integer num = (Integer) iter.next();
System.err.println("第"+j+"次的投资金额="+num.intValue()+"元");
j++;
}
System.err.println("=============over===========");
}
/**
*
* @param n 计算到第n次的时候,所有投资的金额组成的列表
* @param invest 第一次所投资的金额
* @return
*/
private List result(int n, int invest) {
List list = new ArrayList();
list.add(0,new Integer(invest));
for (int i = 1; i <= n; i++) {
List tmpList = null;
if( i<=26 ){
tmpList = list ;
}else{
tmpList = list.subList(i-26,list.size()-1);
}
int result = 0;
int j=0 ;
for (Iterator iter = tmpList.iterator(); iter.hasNext();) {
Integer listj = (Integer) iter.next();
if(iter.hasNext())
result+=listj.intValue()/200*a[(i-1-j)%26];
else
result+=listj.intValue()/200*a[(i-1-j)%26]+listj.intValue()%200;
j++;
}
list.add( new Integer(result));
}
return list;
}
/**
* @param args
*/
public static void main(String[] args) {
int times = 18;
int money = 200*200;
test obj = new test();
//显示开始的投资金额以及每次投资的金额
obj.showAllInvestInfo(times,money);
//得到第times此的回报金额
int result = obj.getInvestMoney(times,money);
System.err.println( "第"+times+"次,就可以投资" +result+"元了" );
//得到所有的投资金额(包括最初的投资)
int allInvestMoney = obj.getAllInvestMoney(times,money);
System.err.println( "加上最初投入的钱("+money+")总共投资"+allInvestMoney +"元");
}
}
以前的递归算法如下:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
public class digui {
//第一次投资的钱
int investMoney = 60000;
//每点的钱数
int moneyPerPoint = 200;
//每点可以投资的最大次数
static int maxTime = 26;
//投资日期
Date investDate = new Date();
//每次每点所能获得的金额,共26次.
int a[] = { 10, 20, 20, 20, 20, 20, 20, 30, 30, 38, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
//截至的日期(在构造函数中设置)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public Date breakDate ; // 计算到此日所获得的全部金额
//到breakDate那天能够获得的金额
int allMoney = 0;
public digui() {
try {
//设置你想获得什么时间的金额
breakDate = sdf.parse("2007-04-19");
} catch (Exception e) {
}
}
/**
* 计算所有日期的金额,并显示他们.
*
*/
public void caculateAllMoney() {
HashMap map = new HashMap();
//获得每次的所获金额
this.caculateDateMoney(this.investDate, this.investMoney,
this.breakDate, map);
//按照时间的顺序显示金额
TreeSet tset = new TreeSet(new DateSort());
tset.addAll(map.keySet());
int i = 1;
for (Iterator iter = tset.iterator(); iter.hasNext();) {
String dateStr = (String) iter.next();
System.err.println("第[" + (i++) + "]次投资日期=" + dateStr + ",投资金额="
+ map.get(dateStr));
}
}
/**
* 计算点数,金额/200就是点数
* @param money
* @return
*/
private int caculatePoint(int money) {
return money / moneyPerPoint;
}
/**
* 递归计算某次投资为止滚动投资的所有投资的金额.
* @param investDate
* @param investMoney
* @param breakDate
* @param map
*/
public void caculateDateMoney(Date investDate, int investMoney,
Date breakDate, Map map) {
Calendar cld = Calendar.getInstance();
cld.setTime(investDate);
for (int i = 0; i < a.length; i++) {
int money = a[i] * (this.caculatePoint(investMoney));
cld.add(Calendar.DAY_OF_YEAR, 15);
if (map.containsKey(sdf.format(cld.getTime()))) {
Integer tmp = (Integer) map.get(sdf.format(cld.getTime()));
map.put(sdf.format(cld.getTime()), new Integer(money
+ tmp.intValue()));
} else {
map.put(sdf.format(cld.getTime()), new Integer(money));
}
if (cld.getTime().after(breakDate)) {
break;
} else {
//滚动计算所有日期的对应的金额
caculateDateMoney(cld.getTime(), money, breakDate, map);
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
digui obj = new digui();
obj.caculateAllMoney();
}
}
/**
* 用于顺序显示结果.
* @author eric
*
*/
class DateSort implements Comparator {
public int compare(Object a, Object b) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date1 = sdf.parse((String) a);
Date date2 = sdf.parse((String) b);
if (date1.after(date2)) {
return 1;
} else {
return -1;
}
} catch (Exception e) {
return -1;
}
}
}
所以,大规模时尽量避免递归!!!
- 我和老婆打赌的结果
- 我和上帝打赌
- 我和我的老婆
- 我和老婆的财运
- 我和老婆的私房话...
- 和李易打赌 我看好雷军的小米手机
- 和小A的打赌-文本框轰炸机
- 老婆心情和我的投入
- 爱我的老婆。
- 写给我的老婆
- 我的老婆
- 我的老婆
- 我的漂亮老婆!
- 我的老婆
- 我的软件工程师老婆
- 我的老婆,黄陈晨
- 我和我老婆的年度阅读清单
- 偷看了我老婆的日记,结果笑了个半死!~@~
- 集合的clone
- 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序
- WIN2000 网络命令手册.pdf下载
- Windows系统如何建立隐藏的超级用户
- 6 Different Version of Windows Vista
- 我和老婆打赌的结果
- 用asp.net还原与恢复sqlserver数据库
- Asp.net直接保存文件到客户端
- 如何从内存中获取图片
- 会话目录及使用终端服务器的负载平衡
- linux->windows移植注意事项
- 读出图片文件到byte数组,然后再得到stdpicture
- XP主题太多了
- 现在注册google帐号可以不用邀请信了