11
public static int multiply2(int num1, int num2) {
    if (num1 == 0 || num2 == 0) {
        return 0;
    }

    else {
        return num1 + multiply2(num1, num2 - 1);
    }

}

我刚刚意识到,编写一个可以确定两个数字的乘积的程序会很有趣,一个或两个数字都是负数。我想使用递归乘法(基本上是重复加法)来做到这一点。有人可以帮我吗?谢谢!

4

8 回答 8

9
if (num1 == 0 || num2 == 0) {
        return 0;
}

else if( num2 < 0 ) {
    return - num1 + multiply2(num1, num2 + 1);
}

else {
    return num1 + multiply2(num1, num2 - 1);
}
于 2012-10-05T07:11:24.037 回答
3
else if (num1 < 0 || num2 < 0) {
    int signum1 = num1 < 0 ? -1 : 1;
    int signum2 = num2 < 0 ? -1 : 1;
    return signum1 * signum2 * multiply(signum1 * num1, signum2 * num2);
} else {

类似的东西

注:有一个signum功能,Math.abs可用于signum * num

于 2012-10-05T07:12:53.153 回答
2

您将测试它是否为负数并减去而不是添加:

public static int multiply2(int num1, int num2) {
    if (num1 == 0 || num2 == 0) {
        return 0;
    }
    else if(num2 > 0){
        return num1 + multiply2(num1, num2 - 1);
    }
    else{
        return -num1 + multiply2(num1, num2 + 1);
    }
}
于 2012-10-05T07:09:55.210 回答
1

如果数字是 -ve,您将需要添加。如果您看到我们只添加第一个数字,而对于第二个数字,我们必须达到的条件是0。所以如果消极做+1如果积极做-1

        else if (num2 < 0)
            return -num1 + multiply2(num1, num2 + 1);
         else
            return num1 + multiply2(num1, num2 - 1);

    System.out.println(multiply2(5, -6));-->-30
    System.out.println(multiply2(5, 6));-->30
于 2012-10-05T07:13:26.813 回答
1

与其在主递归部分多次处理它,不如将其作为边缘情况处理并将其转换为常规情况,因为在数学运算完成之前不会发生赋值和返回。为此,我将 y 转换为正数,然后在结果返回负数情况后将函数的结果作为一个整体取反。

这是我的解决方案:

private static int product(int x, int y) {
    // Negative start edge case
    if (y < 0) {
        return -1 * product(x, y * -1);
    }

    // Edge case (only for speed)
    if (y == 0 || x == 0) {return 0;}

    // Base case
    if (y == 1) {
        return x;
    }

    // Recursion
    return x + product(x, y-1);
}

值得注意的是,即使没有 0 边缘情况,该方法仍然有效。在这种情况下,该方法只需要多做一些就可以获得结果。

测试得出结论,此方法适用于任一参数为 0 和/或负数。

于 2019-04-26T17:01:08.407 回答
0
public static int multiply2(int num1, int num2) {
    if (num1 == 0 || num2 == 0) {
        return 0;
    }

    else {
        int sign2=(int)(Math.abs(num2)/num2);
        return sign2*num1 + multiply2(num1,num2-sign2);
    }

}
于 2012-10-05T07:13:24.603 回答
0

David Wallace 的回答很好,但如果输入是 (1,124) 或 (-1,124),递归深度(方法调用自身的次数)将为 123,效率不高。我建议添加几行来测试 1 或 -1。这是一个完整的例子:

public class Multiply {

    public static void main(String[] args) {

        System.out.print("product = " + multiply(1, 124) );
    }

    public static int multiply(int x, int y) {
        System.out.println("Multiply called: x = " + x + ", y = " + y);

        if (x == 0 || y == 0) {
            System.out.println("Zero case: x = " + x + ", y = " + y);
            return 0;
        }

        else if (x == 1 && y > 0) {
            return y;
        }

        else if (y == 1 && x > 0) {
            return x;
        }

        else if ( x == -1 && y > 0) {
            return -y;
        }

        else if ( y == -1 && x > 0) {
            return -x;
        }

        else if( y == -1 ) {
            System.out.println("y is == -1");
            return -x;
        }

        else if( x == -1 ) {
            System.out.println("x is == -1");
            return -y;
        }

        else if( y < 0 ) {
            System.out.println("y is < 0");
            return -x + multiply(x, y + 1);
        }

        else { 
            System.out.println("Last case: x = " + x + ", y = " + y);
            return x + multiply(x, y - 1);
        }
    }
}

输出:

Multiply called: x = 1, y = 124
product = 124
于 2013-06-03T20:10:48.530 回答
0

好的,所以我实际上正在为家庭作业做这个。递归解决方案实施或使用确定是否需要继续的基本情况。现在,你可能会说,“这到底是什么意思?” 好吧,用外行的话来说,这意味着我们可以简化我们的代码(并且,在现实世界中,可以为我们的软件节省一些开销)——我稍后会解释这一点。现在,问题的一部分是理解一些基本的数学,即负数加负数是负数还是负数(-1 + -1 = -2)取决于您与之交谈的数学老师(我们将看到它在下面的代码中发挥作用)。

现在,这里一些争论。关于它,我稍后会写。

这是我的代码:

public static int multiply(int a, int b)
{
    if (a == 0) 
    {
        return result;
    } 
    else if (a < 0) // Here, we only test to see whether the first param.  
                    // is a negative
    {
        return -b + multiply(a + 1, b); // Here, remember, neg. + neg. is a neg.
    }                                   // so we force b to be negative.
    else 
    {
        result = result + b;
        return multiply(Math.abs(a - 1), b);
    }
}

请注意,这里有两件事做的不同:

  1. 由于第一段的数学原理,上面的代码没有测试第二个参数看第二个参数是否为负(a < 0)(见第一段的粗体字)。本质上,如果我知道我正在将 ( y ) 乘以一个负数 ( -n ),我知道我正在使用-n并将其加在一起​​y次;因此,如果被乘数或乘数为负数,我知道我可以取其中一个数字,使数字为负数,然后一遍又一遍地将数字加到自身上,例如 -3 * 7 可以写成 (-3) + ( -3) + (-3) + (-3)... 等等OR (-7) + (-7) + (-7)

  2. 现在讨论的内容是:上面的代码不会测试第二个数字 ( int b) 是否为0,即乘以0。为什么?嗯,这是个人选择(有点)。这里的辩论必须权衡某事的相对重要性:每个选择的开销(是否运行等于零测试)。如果我们进行测试以查看一侧是否为零,则每次递归调用乘法时,代码都必须计算表达式;但是,如果我们测试是否等于零,那么代码会将一堆零加在一起​​n次。实际上,这两种方法的“权重”相同——因此,为了节省内存,我省略了代码。

于 2014-05-26T23:16:17.917 回答