使用java中的递归查找数字的以2为底的对数

Ges*_*alt 0 java recursion tail-recursion

我正在尝试用 Java 编写一个递归方法来查找 2 的倍数的基数 2 日志。

我已经使用这种递归方法成功计算了日志。

import java.util.*;

class temp
{
    static int log(int number)
    {
        if(number==1)
            return 0;
        return log(number/2)+1;
    }   
    public static void main(String s[])
    {
        Scanner input=new Scanner(System.in);
        System.out.println("Enter Multiple of 2:");
        System.out.println("Log is:"+log(input.nextInt())); //calling log with return value of nextInt()
    }
}   
Run Code Online (Sandbox Code Playgroud)

我搁浅的地方是尝试使用不同的方法来实现相同的程序,在这种方法中,我在递归调用中从 2 开始乘以直到它等于给定的数字。这是我尝试过的:

class logarithmrecursion
    {
        static int step=1;
        static int log(int number)
        {
            final int temp=number;
            if(number>=temp && step!=1)
                return 0;
            step++;
            return log(number*2)+1;
            
        }
    }
Run Code Online (Sandbox Code Playgroud)

在第一次调用期间,number 等于 temp,所以我使用了一个步进变量来防止终止条件的执行。如果我在递归调用中不使用“number”变量,我就没有办法累积前一个乘积但 number 变量已经等于 temp 并且将在下一次递归调用中触发终止条件,因此总是给出输出 1。

我该怎么做才能使这个程序运行?

Boh*_*ian 5

第一个减少版本的固定终止值为 1。

但是第二个版本的终止取决于数量,因此您必须将其传递到递归调用中。因此,您的主函数调用私有递归版本:

static int log(int number) {
    return log(number, 1);
}

private static int log(int number, int current) {
    return current < number ? log(number, current * 2) + 1 : 0;
}
Run Code Online (Sandbox Code Playgroud)

注意:您的算法会将值向上舍入。为了让(更预期)圆润下来的结果,这与同意(int)(Math.log(i) / Math.log(2)),使用这种变化:

private static int log(int number, int current) {
    return current <= number / 2 ? log(number, current * 2) + 1 : 0;
}
Run Code Online (Sandbox Code Playgroud)

这种模式——使用包装函数——在递归的初始状态需要设置一次的情况下很常见,但我们不想让调用者不得不知道什么是实现选择。


您的第一个方法也可以编码为一行:

static int log(int number) {
    return number == 1 ? 0 log(number/2) + 1;
}   
Run Code Online (Sandbox Code Playgroud)