【问题标题】:writing a recursive function to multiply 2 integers, with a twist编写一个递归函数来乘以 2 个整数,有一个扭曲
【发布时间】:2013-11-19 20:46:17
【问题描述】:

这是我的家庭作业。看起来好像这个论坛上的人在寻求类似功能的帮助,但我找不到足够相关的东西供我使用。

在这里;

Nat multiply(Nat a, Nat b) 函数接受 2 个 Nat 类型值。它们包含一个int theValue 值和一个bool isValid 值。第二个几乎无关紧要(就我而言。)

我正在尝试将这两个 Nat 值相乘。这就是我目前所拥有的,尽管随着我越来越沮丧,它会经常变化; [编辑] -> 这是一个稍微修改过的版本;

    if(b.theValue == 1){
    return a;
}
else if(a.theValue == 0 || b.theValue == 0){
    a.theValue = 0;
    return a;
}
else{
    a = add(a, a);
    b = decrement(b);
    return multiply(a, b);
}

[EDIT] 它适用于 1 和 0 的值。我将实施您的有用提示。

限制是我不能直接使用 '+' 运算符,或直接使用 '*' 运算符,它必须是递归的。但是,我可以使用一个 incrementdecrement 函数,它们接受一个 Nat 参数,并将其加一。我也可以使用我自己编写并经过广泛测试的addsubtract 函数。

大多数情况下,我认为我在理解如何修改这些值而不影响另一个值的更改次数时遇到了问题。 IE;在将 b 的相同值添加到 a 时如何达到基本情况?我有点掌握递归的概念,但是这个问题困扰着我。

如您所见,我不确定自己在做什么。这个功能给我的答案是WAY。

任何帮助表示赞赏,并提前致谢。

[编辑] 这些很有帮助,我越来越近了哈哈谢谢。

[编辑] 我请了一位老师帮忙,他指出了看似显而易见的解决方案。此处无需更改标题,以防其他人来搜索;

    if(b.theValue == 1){
    return a;
}
else if(a.theValue == 0 || b.theValue == 0){
    a.theValue = 0;
    return a;
}
else{

    //a = add(a, a);
    b = decrement(b);

    return add(a , multiply(a, b));
}

我跳过了一些与递归相关的基本思维过程。不过,这对我来说很有意义。再次感谢大家。

【问题讨论】:

  • @mah 是的。有什么选择吗?另外,除了零错误还有其他选择吗?第二个 if else 检查 a.theValue == 0 导致一切都为零。
  • 对于初学者来说应该是:if(b.theValue == 1){,因为 0 * 任何东西都是 0,而 1 * 任何东西都是任何东西。 0 实际上是只返回 0 的特例。
  • 您能否添加另一个具有三个参数的函数(对其他人不可见,即static)并调用它?例如:Nat multiply_helper(Nat a, Nat b, Nat original_a) {...} 然后执行:Nat multiply(Nat a, Nat b) { return multiply_helper(a, b, a); }
  • 好吧,我通过向函数添加一个等于 a 但没有改变的参数来实现它。多谢你们。希望我还能得到满分!
  • 我认为更重要的见解是(对于自然数)乘以“a * n = a + a * (n-1)”的递归定义;基本情况留作练习。

标签: c++ recursion multiplication


【解决方案1】:

您应该通过简单的乘法(例如 2*1)手动逐步完成此操作……您可能会发现问题出在a = add(a, b);a*ba+a+a+a+…,直到您拥有 b 的总条款 a。您的例程添加b,而它应该递减b(这实际上是一个加法计数器)。

要将其设置为递归例程,您实际上需要第三个参数……存储要添加的值的东西,因此您可以 a = add(a, original_a); -- original_a 不应在整个过程中被修改操作。

Nat multiply(Nat a, Nat b)
{
    if (a.theValue == 0) return a;
    if (b.theValue == 0) return b;
    return recursive_multiply(a, b, a);
}

Nat recursive_multiply(Nat a, Nat b, Nat adder)
{
    if (b.theValue == 0) return a;
    a = add(a, adder);
    b = decrement(b);
    return recursive_multiply(a, b, adder);
}

【讨论】:

  • 问题是我不确定是否允许修改函数的标题。我可能弄错了。我可能会尝试这个并乐观地提交。
  • 您不必为此修改标题……我建议的方式保留了您分配的 multiply() 功能;它只是添加了一个额外的功能(要么需要首先出现,要么需要原型化,但标题中的任何内容都不是必需的)。
  • 是的,我理解适用于添加功能的相同前提。我不确定这是否允许。结果也不是,但一位老师向我解释了现在看起来最有效的系统。
【解决方案2】:

我想我和你在同一个班,如果是这样,我有一些非常重要的事情要提,这将至关重要地改变你的整个答案。在函数中它提到了这一点:

// 你不能直接访问 Nats 中的字段

这意味着您在这个问题中根本不能使用 a.theValue 或 b.theValue。如果你这样做,你将在该功能上获得 0 分。为了确认你有我的任务,你有没有一个叫做 bool zero (Nat n) 的函数?如果是这样,您必须像使用其他函数(如增量、减量和 NotANat)一样使用这些函数。

这些是您应该在加法、乘法和减法中使用的函数:

// given an integer, create a Nat
// This is the only way you should create Nats!
bool NotANat(Nat n)
{
    return !(n.isValid);
}

// given a Nat, check if it is zero or not
bool zero(Nat n)
{
    if (n.isValid) {
        return n.theValue == 0;
    }
    else
    {
        return false;
    }
}

// given a Nat, returns a Nat one less
// Note: we cannot allow this function to produce a negative value
// so to avoid that, we'll set the invalid flag

Nat decrement(Nat n)
{
    if (n.isValid && n.theValue > 0)
    {
        n.theValue = n.theValue - 1;
    }
    else
    {
        n.isValid = false;
    }
    return n;
}

// given a Nat, returns a Nat one greater
Nat increment(Nat n)
{
    if (n.isValid) {
        n.theValue = n.theValue + 1;
    }
    return n;
}

由于我在您的课堂上并且由于学术诚实而无法讨论答案,但是我可以告诉您您可以做什么。在大多数情况下,您的问题是正确的,但是您的基本案例语句应该使用零函数。

编辑: 既然任务完成了,我现在可以给出答案。这是我的作业,我测试了很多次,效果很好:

// ToDo: add()
//       given 2 Nats a,b, return a Nat that represents the sum a+b
//       you may not use + directly
//       you may not access the fields in the Nats directly
//       you must use recursion!
//       you may use any functions already defined for Nat

Nat add(Nat a, Nat b)
{
    if (zero(b)){
        return a;
    } else {
            return add(increment(a), decrement(b));
    }
}


// ToDo: multiply()
//       given 2 Nats a,b, return a Nat that represents the product a*b
//       you may not use * or + directly
//       you may not access the fields in the Nats directly
//       you must use recursion!
//       you may use any functions already defined for Nat
//       Hint: you should use add()

Nat multiply(Nat a, Nat b)
{
    if(zero (b)){
        return b;
    } else {
        return add(a, multiply(a, decrement(b)));
    }
}


// ToDo: subtract()
//       given 2 Nats a,b, return a Nat that represents the difference a-b
//       you may not use - directly
//       you may not access the fields in the Nats directly
//       you must use recursion!
//       you may use any functions already defined for Nat

Nat subtract(Nat a, Nat b)
{
    if (zero(b)){
       if(NotANat(a){
          return a;
       }else{
          return a;
       }
    } else {
        return subtract(decrement(a), decrement(b));
    }
}

所以基本上我正在使用“bool zero(nat n)”作为所有三个函数的基本情况语句,因为这是用户可以使用的唯一原始函数,而无需直接访问函数中的字段.我们在乘法函数中返回 b,因为当 b 为零时,它将返回 0,因此函数得到满足。您的示例提到如果 b 是一个,那么它将返回 a 作为基本情况。在大多数情况下,这是回答它的常用方法,但正如我所提到的,您不能使用字段,这意味着该函数将被标记为零。因此,这是回答问题的一种方式。这个任务的重点不是不能使用函数进行乘法运算,而是使用您的知识使原始函数工作并正确使用递归。我可能会解释这个错误,因为这是我进入这个的第一年,但如果有人想扩展到这个,将不胜感激。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-28
    • 2021-03-25
    • 1970-01-01
    • 2021-01-24
    • 2023-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多