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,不是的话返回false
    4.完成后上面三题后,看下面的伪代码 (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停止循环再return
    static 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();    }}