7.6 函数的功能
下面的第3行代码是一次函数调用,称为main函数调用func函数
public static void main(String[]args){
int a=6;
int b=func(a);
System.out.println(b);
}
函数的调用,可以出现在main函数,也可以在别的函数。例如A函数调用了B函数,然后main函数又调用了A函数。现在我们要学会这样来“使用”函数。
看下面的题目:
定义一个函数,以一个整数为参数,返回该整数的绝对值。
这个函数能得到一个数字的绝对值,假设这个函数的名称是abs。
现在看下面这道题目:
定义函数,用Java写出函数f(x)=x*x+5|x|+6,x的类型是整数。
这道题目里面又有一个绝对值,我们可以使用已经写好的绝对值函数,来完成这道题:
public static int abs(int x){
return x>0?x:-x;
}
public static int func2(int x){
int y=x*x+5*abs(x)+6;
return y;
}
abs(x)函数是得到x的绝对值,然后func2调用了abs函数(第5行代码)。在main函数调用一下func2试试?
如果把所有代码都到一个函数里面,那么就会复杂一点,同时会有重复的代码存在,这类冗余代码是要避免的。
其实,函数的最主要作用是:将复杂问题化成若干个简单函数,然后逐个解决。
下面我们来用这个分解问题的方法,来解决这个问题:
输入两个数字,求它们的最大公约数。
最大公约数是两个数字都能整除的最大数字。解题思路是这样的:
1.i从2开始,max为1,num为两个数较小的数字
2.假如i小于等于num,进入第3步,否则算法结束,max就是最大公约数
3.判断i能不能被两个数整除,如果能,将i的值赋给max。进入第4步。
4.i++,回到第2步
关于这些初值这么设置,是这样的原因:
i没必要从1开始,因为1必定能被任何整数整除,
max初值设定为1,如果max的值一直都没有改变,那么1就是两个数的最大公约数,所以max的初值不能随便设置(例如设为0是不行的)
num设置为两个数中较小的数,是为了减少循环次数。
可分解成下面这些函数:
int min(int a,int b),返回a和b较小的那个数。
boolean canBeDivide(int a,int b),a能被b整除,返回true,否则返回false
下面我们来实现它们,最终通过函数调用,完成最大公约数。
练习题
-
数学函数分解1.定义函数min,两个数字为参数,返回较小的那个数。 (10分) [编程]2.定义函数max,输入两个整数,返回较大的那个数。 (10分) [编程]3.定义函数canBeDivide,参数是两个数字x和y,如果x能被y整除,那么返回true,否则返回false。 (10分) [编程]canBeDivide(int x,int y)
也就是x%y的值是0返回true,不是的话返回false4.完成后上面三题后,看下面的伪代码 (10分) [编程]剩下的工作就比较简单了。最大公约数的这个算法的核心是穷举法,也就是每个i都拿来尝试,而细分的函数设计,能把大问题分解成小问题,便于问题的解决
根据伪代码完成此函数static int zdgys(int x,int y){ int num=调用min函数,算出x和y较小的数; int max=1; for(int i=2;i <= num;i++){ // i能整除x并且i能整除y,使用canBeDivide函数来判断,如果i可以被x和y整除,那么i是当前找到的最大的公约数 if(调用canBeDivide判断x能被i整除 并且 调用canBeDivide判断y能被i整除) max=i; } return max;}5.完成最小公倍数函数zxgbs,接收两个整型参数,返回两个参数的最小公倍数 (10分) [编程]解题思路是这样的:
(0) 将其中较大的数字赋给k,
(1)看k能不能整除两个数字,如果可以,那么到(2),否则到(3)
(2)这个k就是最小公倍数,直接返回i,算法结束。
(3)k加1,回到(1)。
那么首先这个循环,需要找到较大的那个数,可分解成下面这个函数:
整除关系的话,可以使用上一节的canBeDivide函数。
最小公倍数不会大于这两个数字的乘积,可用作循环结束的条件
最后不管是中间打断还是循环到结束,i都是最小公倍数,i是最终返回值6.最大公约数另外一个解题思路是这样的: (10分) [编程]i从两个数较小的数开始
(1)看i能不能被两个数字整除,如果可以,那么到(2),否则到(3)
(2)这个i就是最大公约数,直接返回i,算法结束。
(3)i减去1,回到(1)。
尝试下完成此算法,需要使用已经定义好的min和CanBeDivide函数:
注意函数return语句在这里的作用:相当于break,因为遇到return,整个函数计算就结束了,不需要用break停止循环再returnstatic int zdgys(int x,int y){ int num=调用min函数,算出x和y较小的数; for(int i=num;i >= 1;i--) // i能整除x并且i能整除y,使用canBeDivide函数 if(调用canBeDivide判断x能被i整除并且调用canBeDivide判断y能被i整除) return i; return 1;}7.定义函数isPrime,判断整型参数x是否素数 (10分) [编程]判断参数x是否是素数。
如果x是素数,返回true,如果不是则返回false。
算法:
(1)i=2,进入第2步
(2)如果i小于x,测试x能否被i整除,如果可以,返回false算法结束;如果都不符合,进入第3步;
(3)i++,如果i等于x,返回true算法结束;否则回到第2步
i从2开始逐个尝试x能否被i整除,假如有某个数字可以整除,那么马上可以判断不是素数,可以立刻返回false,这就是第2步的逻辑;然而要判断是素数,必须整个循环走完,同时循环走完就能返回true,所以第3步里当i等于x的时候,说明i已经加到x都一直没找到,那么x是素数。。
我们有之前的整除判断函数canBeDivide,这里仍然可以使用8.定义一个函数printPrime,接收一个参数x,没有返回值。 (10分) [编程]打印x以内所有的素数,要求调用上面的isPrime函数。
此题要求把上一题的isPrime函数定义也写上 -
用函数解决二重循环打印1.genChar (10分) [编程]生成连续n个字符写成一个函数genChar,它有两个参数,第一个是要打印的字符,第二个是打印的数量n,返回值是就是n个连续的字符,返回类型是String
public void main(String[]args){ String c=genChar("*",5); //将打印5个* System.out.println(c);}2.使用genChar打印矩阵(需要完成上一题genChar函数的定义) (10分) [编程]下面的代码会打印10*10个字符'*'的矩阵,使用的是genChar
参考代码,打印一个5*6(5行6列)的符号为*的矩阵
上一节定义的genChar函数需要贴在main函数上方/*上一题genChar函数定义粘贴处,略 *//*这是使用了函数genChar打印10*10矩阵的代码 */public static void main(String[]args){ int i=0; while(i < 10){ String line=genChar("*",10); System.out.println(line); i++; }}3.使用genChar函数,打印一个由*组成的直边在右的直角三角形 (10分) [编程]打印十行
第一行,9个空格打印1个*
第二行,打印8个空格2个*
……
第十行,打印0个空格10个*
总结起来就是:
每行打印的空格数为10-i,打印的*数为i
上一节定义的genChar函数需要贴在main函数上方4.使用genChar重构等腰三角形的打印 (10分) [编程]这段代码可以打印一个等腰三角形,参照此代码
现在,用genChar函数重写一次
上一节定义的genChar函数需要贴在main函数上方public static void main(String[]args){ for(int i=1;i <= 10;i++){ for(int j=1;j <= 10-i;j++) System.out.print(" "); for(int j=1;j <= 2*i-1;j++) System.out.print("*"); System.out.println(); }}