第2章 身边的数学问题
在我们的身边有许多有趣的数学问题,经常编写程序来解决数学问题可以增强我们的逻辑思维能力,开发我们的智力,同时使我们的生活变得多姿多彩。本章将让你学会如何通过程序设计来解决一些有趣的数学问题。 2.1 黑色星期五 1.问题描述
黑色星期五源于西方的宗教信仰与迷信:耶稣基督死在星期五,而13是不吉利的数字。两者的结合令人相信当天会发生不幸的事情。星期五和数字13都代表着坏运气,两个不幸的个体最后结合成超级不幸的一天。所以,不管哪个月的13日又恰逢星期五就叫“黑色星期五”。找出未来几年哪些天是“黑色星期五”。 2.问题分析
这个问题是一个很经典的逻辑判断的题目。通过问题描述,我们知道“黑色星期五”要满足两个条件,一是当天是13号,二是当天还是星期五。我们可以从起始日期开始,循环判断每天是否同时满足这两个条件就可以了。这个方案很容易想到,但是一年三百多天,一天天判断是不是太慢了,有人也许会说,计算机速度快,很快就能处理完。有没有更好的办法呢,当然有了,其实条件说的很明白啊,条件之一必须满足是13号,那么我们就判断13号是不是星期五不就可以了吗,一年日期是13号的,也就12个月里,每个月一个13日,这样我们判断的日期也就缩小到每个月的13号,一年最多判断12次,比较范围大大缩小。每个月的13号到底是星期几呢?Java中的日期处理类Calendar提供的方法能够很容易地获得。 (1)确定程序框架
通过前面的分析,一年内有几个“黑色星期五”,要分别判断每个月的13号是不是星期五,可以通过循环语句循环12次来实现。如果要找到未来n年内的黑色星期五,外层再用循环语句控制循环n次,这样我们就可以写出程序框架了。代码如下:
while(k for (int i = 0; i < 12; i++) { if(当前月的13号是星期五) { System.out.println(\黑色星期五:\当前日期); } } year++; //year代表起始年份 k++; } 下面我们就需要考虑如何判断每个月13号是星期几。 (2)判断13号是星期几 每个月的13号到底是星期几呢?可以通过Java中的日期处理类Calendar提供的方法来获得。使用Calendar类代表特定的时间,需要首先创建一个Calendar的对象,然后再设定该对象中的年月日参数来完成,最后根据Calendar类对象信息来获得星期几。对应代码如下: //创建一个代表2012年1月13日的Calendar对象 Calendar cal = Calendar.getInstance(); //创建对象 cal.set(2012, 1, 13); //日期的设置 cal.get(Calendar.DAY_OF_WEEK)-1 //星期的获得 cal.getTime() //日期的获得 我们要判断每个月的13号是不是星期五,所以只要把日期的设置方法set()第二个月份参数用循环变量来代替即可。同理,如果要对其他年份进行设置,也只要把第一个年份参数替换掉即可。 (3)完整程序 现在我们就需要把刚才的程序进行组合,构成我们的完整程序: import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Scanner; public class ch2_1 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input=new Scanner(System.in); //获取控制台输入对象 System.out.print(\请输入起始年份:\ int year=input.nextInt(); //从键盘接收起始年份 System.out.print(\请输入打算输出未来几年:\ int n=input.nextInt(); //从键盘接收打算输出年份 getBlackFri(year,n); //调用得到“黑色星期五”方法 } //打印未来几年的黑色星期五,判断每个月的13号是否是星期五 public static void getBlackFri(int year,int n) { //year为输入的年份,n为未来多少年 SimpleDateFormat sdf = new SimpleDateFormat(\E\ //日期格式对象 int k=0; Calendar cal = Calendar.getInstance(); //获得日历对象 while(k { for (int i = 0; i < 12; i++) //内循环控制月份 { cal.set(year,i,13); //设置日期 if(5==(cal.get(Calendar.DAY_OF_WEEK)-1)) //判断是否是星期五 { System.out.println(\黑色星期五:\ //输出格式化日期 } } year++; //年份增加 k++; } } } 2.2 个人所得税 1.问题描述 个人所得税是指国家对个人所得额征收的一种税。个人工资薪金所得采用超额累进税率,纳税人所得越高,课税越重。“高收入者多纳税,低收入者少纳税”是个人所得税的显著特点。现行的9级超额累进个人所得税税率表如表2-1所示。 表2-1 所得税税率表 级数 全月应纳税所得额(减去3500元后的余额) 税率/% 1 不超过500元的部分 5 2 超过500元至2000元的部分 10 3 超过2000元至5000元的部分 15 4 超过5000元至20000元的部分 20 5 超过20000元至40000元的部分 25 续表 级数 全月应纳税所得额(减去3500元后的余额) 税率/% 6 超过40000元至60000元的部分 30 7 超过60000元至80000元的部分 35 8 超过80000元至100000元的部分 40 9 超过100000元的部分 45 目前,上表中“全月应纳税所得额”是从月工资、薪金收入中减去3500元后的余额。试根据上述资料编程计算个人所得税,并根据你的家庭成员的月收入求出每月需要缴纳多少个人所得税。 2.问题分析 这个问题是一个很经典的条件分支应用的题目。假设全月应纳税所得额属于第i级别,那么,应缴纳税款=前i–1级累加税款+当前级别超出部分×当前级别税率。 例如,某人月工资、薪金收入4020元,减去3500元,应纳税所得额为520元,由税率表可知,其中500元税率为5%,另外20元税率为10%,所以此人应缴纳个人所得税:500×5%+20×10%=27元。 当前级别超出部分和当前级别税率根据税率表很容易得到,关键是前i–1级累加税款,我们可以通过计算,把每个级数的前i–1级累加税款先算出来,得到一个升级的税率表,如表2-2所示。 表2-2 升级版所得税税率表 级数 全月应纳税所得额(减去3500元后的余额) 税率/% 扣除累加数 1 不超过500元的部分 5 0 2 超过500元至2000元的部分 10 25 3 超过2000元至5000元的部分 15 175 4 超过5000元至20000元的部分 20 625 5 超过20000元至40000元的部分 25 3625 6 超过40000元至60000元的部分 30 8625 7 超过60000元至80000元的部分 35 14625 8 超过80000元至100000元的部分 40 21625 9 超过100000元的部分 45 29625 (1)确定程序框架 从表2-2中,我们可以发现,一共有9个级数,也就是9个分支,这样我们就可以写出程序框架了。代码如下: public class ch2_2 { public static void main(String[] args) { ... if(b <=500) { //计算当前级数的税款 } else if(b <=2000) { //计算当前级数的税款 } else if(b <=5000) { //计算当前级数的税款 } else if(b <=20000) { //计算当前级数的税款 } else if(b <=40000) { //计算当前级数的税款 } else if(b <=60000) { //计算当前级数的税款 } else if(b <=80000) { //计算当前级数的税款 } else if(b <=100000) { //计算当前级数的税款 } else { //计算当前级数的税款 } ... } } 下面我们就需要计算每个级数的税款。 2)计算每个级数的税款 根据前面的分析,结合表2-2,可以很容易计算每级的税款。假设应纳税所得额为10000元,由表2-2可知,级数为4,税率20%,扣除累计数625,所以应交税款为:625+(10000–5000)*20%,即: t=625+(b-5000)*0.2 //b代表应纳税所得额,t代表应交税款 同理可以写出各个级数分支的代码。 (3)完整程序 现在我们就需要把刚才的程序进行组合,构成我们的完整程序: import java.util.Scanner; public class ch2_2 { public static void main(String[] args) { System.out.print(\请输入个人收入:\ Scanner input=new Scanner(System.in); //获取控制台输入对象