分享到:
发表于 2013-01-31 14:21:06 楼主 | |
内容简介: 《Java趣味编程100例》讲解了100个各种类型的Java编程趣味题的求解过程,旨在帮助读者培养编程兴趣,拓宽Java编程思维,提高Java编程能力,掌握用程序设计解决实际问题的方法与技巧。本书取材注重趣味性与实用性,内容涵盖了Java编程的基础知识和常用算法,讲解时给出了实例的详细代码及注释。本书附带1张光盘,收录了本书配套多媒体教学视频及实例源文件,可大大方便读者高效、直观地学习本书内容。 《Java趣味编程100例》共分11章。第1章介绍了8个常见的变幻多姿的图表;第2章介绍了12个身边的数学问题;第3章介绍了8个趣味整数;第4章介绍了9个趣味素数;第5章介绍了8个趣味方程;第6章介绍了8个趣味分数;第7章介绍了10个逻辑推理;第8章介绍了8个趣味变幻;第9章介绍了9个定理与猜想;第10章介绍了9个趣味游戏;第11章介绍了11个其他趣味问题。 《Java趣味编程100例》适合高校、职业技术院校及社会培训学校的学生阅读,也适合Java编程爱好者阅读,还可作为各级程序设计选拔赛和全国青少年信息学奥林匹克竞赛的参考书。
|
|
楼主热贴
个性签名:无
|
发表于 2013-03-08 09:52:56 14楼 | |
学习学习 | |
发表于 2013-01-31 14:42:52 13楼 | |
2.13 小 结 我们的身边到处都有数学,求解问题的过程充满乐趣。本章详细讲解了身边的数学问题,包括黑色星期五、个人所得税、存钱问题、赛场统分、肇事车辆、分糖果、天平称物、平分七框梨、一维多项式计算、线性方程求解、非线性方程求解等经典案例,读者可以根据个人喜好,有选择地深入研究,提出自己更好的改进方法,体会编程的乐趣。 |
|
发表于 2013-01-31 14:41:29 12楼 | |
2.12 非线性方程求解(二分法) 1.问题描述 非线性方程的求解除了牛顿迭代法之外,二分法也是一种简单高效的求解方法。在有的地方,二分法也称之为对分法。二分法是逐次把有根区间分半,直到找到根或有根区间的长度小于给定精度为止。 用二分法求解如下的非线性方程的近似解: 2x3–5x–1=0 2.问题分析 对于函数f(x),如果x=c时,f(c)=0,那么把x=c称之为函数f(x)的零点。求解方程就是计算该方程所有的零点。对于二分法,假定非线性方程f(x)在区间(x,y)上连续。如果存在两个实数a和b属于区间(x,y),使得满足如下式子: f(a)*f(b)<0 也就是说f(a)和f(b)异号,这就说明在区间(a,b)内一定有零点,也就是至少包含该方程的一个解。然后,我们计算f[(a+b)/2]。此时,假设如下的条件: f(a)<0,f(b)>0,a 我们可以根据f[(a+b)/2]的值来判断方程解的位置: |
|
发表于 2013-01-31 14:41:01 11楼 | |
2.11 非线性方程求解(牛顿迭代法) 1.问题描述 非线性方程指方程中包含一个变量的幂次不是1次。例如:y=4x2–3、y=sin(x)–3x+1等等。这种方程多数不存在求根公式,从而求精确根非常困难,甚至不可能,从而寻找方程的近似根就显得特别重要。牛顿迭代法是牛顿在17世纪提出的一种求解方程f(x)=0的方法。 用牛顿迭代法求解如下的非线性方程在x0=2.0附近的方程的解: 2.问题分析 牛顿迭代法的原理:设r是f(x)=0的根,选取x0作为r初始近似值,过点(x0,f(x0))做曲线y=f(x)的切线L,L的方程为y=f(x0)+f '(x0)(x–x0),求出L与x轴交点的横坐标 x1=x0–f(x0)/f '(x0),称x1为r的一次近似值,过点(x1,f(x1))做曲线y=f(x)的切线,并求该切线与x轴的横坐标x2=x1–f(x1)/f '(x1)称x2为r的二次近似值,重复以上过程,得r的近似值序列{Xn},其中Xn1=Xn–f(Xn)/f '(Xn),称为r的n1次近似值。上式称为牛顿迭代公式。 (1)确定程序框架 上面详细分析了牛顿迭代法求解非线性方程的过程,由分析可知,除了非线性方程本身,还要用到非线性方程曲线的切线,所以还要准备好非线性方程的导数方程,然后通过牛顿迭代公式进行迭代,求出方程的近似解。程序的框架如下: public class ch2_11 { public static void main(String[] args) { //构造非线性方程 //构造非线性方程的导数方程 //通过迭代公式求解 } } (2)构造非线性方程 为简化代码,这里直接写出非线性方程。代码如下: static double func(double x) //待求解方程 { return x*x*x*x-3*x*x*x+1.5*x*x-4.0; } (3)构造导数方程 为简化代码,这里直接写出非线性方程。代码如下: static double dfunc(double x) //导数方程 { return 4*x*x*x-9*x*x+3*x; } (4)通过迭代公式求解 从前面的分析可知,其中Xn1=Xn–f(Xn)/f '(Xn)为牛顿迭代公式,通过它很容易写出代码,代码如下: /** *x代表初始值 *maxcyc代表迭代次数 *precision代表精确度 *得到结果,返回值为1,否则,返回值为0 */ static int NewtonMethod(double[] x,int maxcyc,double precision) { double x0,x1; int i; x0=x[0]; //参数传递迭代初始值 i=0; while(i if(dfunc(x0)==0.0) //若通过初值,方法返回值为0 { System.out.print("迭代过程中导数为0!n"); return 0; } x1=x0-func(x0)/dfunc(x0); //牛顿迭代计算 if(Math.abs(x1-x0) { x[0]=x1; //返回结果 return 1; } else //未达到结束条件 { x0=x1; //准备下一次迭代 } i++; //迭代次数累加 } System.out.print("迭代次数超过预设值!仍没有达到精度!n"); return 0; } (5)完整程序 现在我们就需要把刚才的程序进行组合,构成我们的完整程序: public class ch2_11 { static double func(double x) //待求解方程 { return x*x*x*x-3*x*x*x+1.5*x*x-4.0; } static double dfunc(double x) //导数方程 { return 4*x*x*x-9*x*x+3*x; } static int NewtonMethod(double[] x,int maxcyc,double precision) { double x0,x1; int i; x0=x[0]; //参数传递迭代初始值i=0 while(i if(dfunc(x0)==0.0) //若通过初值,方法返回值为0 { System.out.print("迭代过程中导数为0!n"); return 0; } x1=x0-func(x0)/dfunc(x0); //牛顿迭代计算 if(Math.abs(x1-x0) x[0]=x1; //返回结果 return 1; } else //未达到结束条件 { x0=x1; //准备下一次迭代 } i++; //迭代次数累加 } System.out.print("迭代次数超过预设值!仍没有达到精度!n"); return 0; } public static void main(String[] args) { double precision; int maxcyc,result; double[] x={2.0}; //初始值 maxcyc=1000; //迭代次数 precision=0.00001; //精度 result=NewtonMethod(x,maxcyc,precision); if(result==1) //得到结果 { System.out.printf("方程x*x*x*x-3*x*x*x+1.5*x*x-4.0=0n在2.0附 近的根为:%fn",x[0]); } else //未得到结果 { System.out.print("迭代失败!n"); } } } |
|
发表于 2013-01-31 14:40:26 10楼 | |
2.10 线性方程求解 1.问题描述 方程中任何一个变量的幂次都是1次,如何求解下面的线性方程组: 2.问题分析 线性方程组的求解方法很多,其中高斯消元法是比较经典的方法。我们这里就用高斯消元法来解这个线性方程组。 下面来看看高斯消元法的基本原理。对于一个线性方程组如下: AX=B 其中,A为系数矩阵,X为变量列矩阵,B为常数列矩阵。假设该方程组有equnum个方程,每个方程有varnum个变量。我们可以将系数矩阵A和常数列矩阵B组合成一个增广矩阵A',然后对该矩阵中的每一个元素进行消元操作。 也就是说,循环处理矩阵的0~equnum–1行(用k表示当前处理的行),并设当前处理的列为col(设初值为0),每次找第k行以下(包括第k行)col列中元素绝对值最大的列与第k行交换。如果col列中的元素全为0,那么则处理col+1列,k不变。 下面我们就以上面的线性方程组来演示高斯消元法的执行过程。所要求的线性方程组的增广矩阵为: 第1次消元: 主元在第2行,找到主元行对调后: 消元后: 第2次消元: 主元在第2行,不用对调,消元后: 经过消元后,再按以下公式执行回代过程,得到方程组各变量的解: 其中:k=n-1,…,1。 在整个算法处理的过程中,我们可以根据高斯消元得到的行阶梯矩阵的值来判断该方程组解的形式。主要有如下几种情况: |
|
发表于 2013-01-31 14:39:45 9楼 | |
您的内容正在火速审核中,请稍等 |
|
发表于 2013-01-31 14:39:11 8楼 | |
您的内容正在火速审核中,请稍等 |
|
发表于 2013-01-31 14:33:05 7楼 | |
2.8 平分七框梨 1.问题描述 甲、乙、丙三位渔夫出海打鱼,他们随船带了21只箩筐。当晚返航时,他们发现有7筐装满了鱼,还有7筐只装了半筐鱼,另外7筐则是空的。由于他们没有秤,只好通过目测认为7个满筐鱼的重量是相等的,7个半筐鱼的重量也是相等的。在不将鱼倒出来的前提下,怎么将鱼和筐平分为三份? 2.问题分析 这个问题可以采用穷举法。根据题意可以知道:每个人应分到7个箩筐,每人各3.5筐鱼。可以采用3*3数组fisherman来表示三个人分到的东西。其中每个人对应数组fisherman的一行,数组的第0列存放分到的鱼的满筐数,数组的第1列存放分到的半筐数,数组的第2列存放分到的空筐数。由题目可以推出: |
|
发表于 2013-01-31 14:32:25 6楼 | |
您的内容正在火速审核中,请稍等 |
|
发表于 2013-01-31 14:31:09 5楼 | |
2.6 分 糖 果 1.问题描述 10个小孩围成一圈分糖果,老师分给第1个小孩10块,第2个小孩2块,第3个小孩8块,第4个小孩22块,第5个小孩16块,第6个小孩4块,第7个小孩10块,第8个小孩6块,第9个小孩14块,第10个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块。问经过这样几次后大家手中的糖的块数一样多?每人各有多少块糖? 2.问题分析 分糖的过程是一个重复的过程。根据分糖的游戏规则,我们不停地重复分糖的步骤,我们可以用一个数组存放每个小孩手中的糖,通过循环修改数组中的数,最终达到都相等为止。 (1)确定程序框架 通过前面的问题分析,我们可以定义一个数组存放10个小孩的糖,如果数组里的值不相等就通过循环修改数组的值,修改完后接着判断是不是有奇数,如果有就加1,然后再判断是否相等,不相等再分,循环反复,直至相等为止。程序的框架如下: public static void main(String args[]) { int tang[]={10,2,8,22,16,4,10,6,14,20}; int times=0; //记录分糖果次数 //如果小孩手中的糖果不相等,就继续分糖果 while(isSame(tang)==false) { //分糖果 times++; //次数加1 //糖果为奇数的向老师要糖果 } System.out.println("分糖果次数:"+times); System.out.println("每个人最终的糖果个数:"+tang[0]); } } (2)分糖果 由问题描述可知,所有的小孩同时将手中的糖分一半给右边的小孩,为了防止最后一个小孩的糖果个数被覆盖了,我们可以先把最后一个小孩(即第10个小孩)的糖果个数先临时保存下来,然后把第9个小孩的糖果一半加上第10个小孩的糖果一半给第10个小孩,依次,把第8个小孩的糖果一半加上第9个小孩的糖果一半给第9个小孩,……,把第1个小孩的糖果一半加上第2个小孩的糖果一半给第2个小孩,最后把临时保存下来的第10个小孩的糖果个数一半加上第1个小孩的糖果一半给第1个小孩,这样分糖果分了一遍。代码如下: int m=tang[9]; //防止被覆盖,备份 for(int i=9;i>0;i--) //循环分糖果 { tang=tang/2+tang[i-1]/2; } tang[0]=tang[0]/2+m/2; //最后一个小孩分糖果 (3)糖果为奇数的向老师要糖果 由问题描述可知,糖块数为奇数的人可向老师要一块。这个问题比较简单,我们可以通过循环判断数组中的数字是不是奇数,进而是否加1操作。代码如下: //糖果为奇数的向老师要糖果 for(int i=0;i<10;i++) if(tang%2!=0) tang+=1; (4)判断每个小孩手中的糖果个数是否相等 由问题描述可知,是否继续分糖的条件是,每个小孩手中的糖果是否一样多。我们可以采用循环比较数组相邻两个数字是否相等,相等则计数器(初始值为0)的个数加1,如果个数全相等,那么计数器的值应该为数组的长度减1。代码如下: public static boolean isSame(int[] a) { int n=0; boolean b=false; //是否相等,标志 for(int i=0;i if(a==a[i+1]) //如果相邻两个数相等,计数器加1 { n++; } if(n==a.length-1) //全部相等判断 b=true; } return b; } (5)完整程序 现在我们就需要把刚才的程序进行组合,构成我们的完整程序: public class ch2_6 { /** * 判断是否全相等,全相等返回true */ public static boolean isSame(int[] a) { int n=0; boolean b=false; //是否相等,标志 for(int i=0;i if(a==a[i+1]) //如果相邻两个数相等,计数器加1 { n++; } if(n==a.length-1) //全部相等判断 b=true; } return b; } /** * 显示数组的值 */ public static void show(int[] a) { if (a == null) //判断数组是否为空 System.out.println("Array = null"); for (int i = 0; i < a.length; i++) //循环输出数组元素 { System.out.print(a + " "); } System.out.println(); } public static void main(String args[]) { int tang[]={10,2,8,22,16,4,10,6,14,20}; //最初小孩手中的糖果个数 int times=0; boolean b=true; while(isSame(tang)==false) //判断糖果是否分配好,没有就继续分 { int m=tang[9]; //防止被覆盖,备份 for(int i=9;i>0;i--) //循环分糖果 { tang=tang/2+tang[i-1]/2; } tang[0]=tang[0]/2+m/2; //最后一个小孩分糖果 //记录分糖果次数 times++; System.out.print("第" + times+ "次分之后结果: "); show(tang); //显示结果 //糖果为奇数的向老师要糖果 for(int i=0;i<10;i++) if(tang%2!=0) //如果为奇数,要一个糖果 tang+=1; } System.out.println("分糖果次数:"+times); System.out.println("每个人最终的糖果个数:"+tang[0]); } } |
|
发表于 2013-01-31 14:30:24 4楼 | |
您的内容正在火速审核中,请稍等 |
|
发表于 2013-01-31 14:28:59 3楼 | |
您的内容正在火速审核中,请稍等 |
|
发表于 2013-01-31 14:27:56 2楼 | |
您的内容正在火速审核中,请稍等 |
|
发表于 2013-01-31 14:25:23 1楼 | |
您的内容正在火速审核中,请稍等 |
|
针对ZOL星空(中国)您有任何使用问题和建议 您可以 联系星空(中国)管理员 、 查看帮助 或 给我提意见