【问题标题】:How can I make one recursive function which does division using only addition and only 2 variables如何制作一个仅使用加法和仅使用 2 个变量进行除法的递归函数
【发布时间】:2021-02-07 08:34:03
【问题描述】:

我最近得到了一项学校作业,要创建一个递归函数,该函数只使用加法(不允许减法)进行除法,并且只有 2 个变量。

编辑:基于 cmets 的几点说明:

  • n1 除以 n2。 (n1:n2)

  • 答案应该是一个整数 (int),您可以将 n2 放入 n1 中的次数(8:3 应该得到 2,8:4 也应该得到 2)。

  • 您可以假设输入只是正整数。

按照cmets的要求,我会尽量把作业翻译成英文,尽量准确:

编写一个名为“PDiv”的递归函数,它获取两个正整数并返回它们的整数商,仅使用加法运算。

我尝试使用 2 个递归函数来实现,如下所示:(赋值只需要一个函数,因此不是正确答案)

public static int PDiv(int n1, int n2)
{
    if (n1 < n2)
        return 0;
    else if (n1 == n2)
        return 1;
    else
        return PDiv(n1, n2 + n2, n2) + 1;
}

public static int PDiv(int n1, int n2, int con)
{
    if (n1 < n2)
        return 0;
    else if (n1 == n2)
        return 1;
    else
        return PDiv(n1, n2 + n2, con) + 1;
}

除此之外,我还尝试了一个确实有效的方法,但它假装很聪明,而不是真正做加法,而是加上减号(基本上是减法)。示例:

public static int PDiv(int n1, int n2)
{
    if (n1 < n2)
        return 0;
    else if (n1 == n2)
        return 1;
    else
        return PDiv(n1 + -n2, n2) + 1;
}

如果有人知道我如何让它发挥作用,我很想听听!提前致谢!

【问题讨论】:

  • n1 是被除数,n2 是除数吗?您是否只想要一个整数商,而忽略任何可能的余数?
  • @Idle_Mind 刚刚用你的笔记更新了帖子。是的,n1 是被除数,n2 是除数。是的,我只是忽略任何余数的整数。
  • 您是否必须处理一个或两个操作数为负数?
  • 有了“并且只有2个变量”的规定,感觉接收三个参数的辅助函数就是作弊。你能贴一张作业的图片,或者它的确切措辞吗?
  • @Idle_Mind 尽我所能尽可能准确地翻译作业并将其编辑到帖子中(在引用中)。谢谢。

标签: c# algorithm recursion division addition


【解决方案1】:

你也可以把它写成一种方法:

public int recursive_div(int a, int b)
    {
        if (a < b)
        {
            return 0;
        }
        else if (b == 0)
        {
            return -1;
        }
        else if (a == b)
        {
            return 1;
        }
        else
        {
            return  recursive_div(a-b,b) +1 ;
        }
    }

返回 -1 只是一个被 0 错误潜水的捕获值。

【讨论】:

    【解决方案2】:

    下面是我们如何通过纯粹的加法、比较和赋值操作以及两个参数来完成它,只要我们允许一个元组返回值。 C#代码:

    using System;
    
    public class Test
    {
        // Returns (floor(n / m) * m, floor(n / m))
        public static (int, int) f(int n, int m){
            if (n < m)
                return (0, 0);
            if (n == m)
                return (n, 1);
      
            (int _n, int k) = f(n, m + m);
    
            if (_n + m > n)
                return (_n, k + k);
        
            return (_n + m, k + k + 1);
        }
    
        public static void Main()
        {
            for (int n=1; n<200; n++){
                for (int m=1; m<n; m++){
                    (int _n, int nm) = f(n, m);
                    if (nm != n / m)
                        Console.WriteLine($"Mismatch: { n }, { m }") ;
                }
            }
    
            Console.WriteLine("Test done.");
        }
    }
    

    【讨论】:

      【解决方案3】:

      这是我们可以实现此目的的一种方法,前提是我们可以使用模运算符和局部变量。

      这个想法是,如果我们知道PDiv(n, m + m),我们只需要知道我们是否还能再添加一个m

      C#代码:

      using System;
      
      public class Test
      {
          public static int PDiv(int n, int m)
          {
              if (n < m)
                  return 0;
              if (n == m)
                  return 1;
        
              int k = PDiv(n, m + m);
      
              return k + k + (n % (m + m) < m ? 0 : 1);
          }
      
          public static void Main()
          {
              Console.WriteLine(PDiv(21, 3));
          }
      }
      

      【讨论】:

      • 我其实也喜欢这个答案,但是当你使用 % 时,我认为它在作业中是不允许的。您的最后一个循环对分配限制很有用,实际上我对其进行了一些修改,使其具有 If 语句而不是三元条件,因为我们还没有在学校学习过那些(?和:)
      • @AmitZwilling 我真的很好奇答案是什么!请告诉我们:)
      • 我一定会的!我明天有课,所以我会请老师告诉我们他的解决方法!
      • @AmitZwilling 可能不接受我的回答,因为有人可能仍然有有趣的想法,但如果问题的答案已被接受,他们将不太可能看这个问题。
      • 有道理,做到了。感谢您的所有帮助!
      【解决方案4】:
      d = a/b 
      d * b + r = a
      

      第二行给出了如何以递归方式解决这个问题的想法。 忽略余数 (r),将 b 相加直到 d*b &gt; a。有了这个,剩下要做的就是跟踪我们必须将 b 加在一起的次数,直到它大于 a

      int div_loop(int dividend, int divisor, int x, int n) {
        if (x > dividend)
           return (n-1);
        return div_loop(dividend, divisor, (x + divisor), (n+1));
      }
      int div(int dividend, int divisor) {
        return div_loop(dividend, divisor, 0, 0);
      }
      

      这应该符合要求,因为要求不禁止编写辅助函数。并且主函数只有两个参数,而且是递归解,只使用加法。

      如果 C# 有嵌套函数(不确定现在是否有,但我上次用 C# 编程时没有),div_loop() 可以嵌套在 div() 函数中,内部函数可以被视为实现详细信息(并且少了 2 个参数)。例如,在 F# 中,这可能如下所示:

      let div dividend divisor =
        let rec operate x n =
          if x > dividend
          then (n - 1)
          else operate (x + divisor) (n + 1)
        operate 0 0
      

      Microsoft c# documentation 看来,C# 现在支持嵌套函数,名称为“本地函数”。

      因此,您可以满足所有要求:

      int pdiv(int dividend, int divisor) {
        return div_loop(0, 0);
        int div_loop(int x, int n) {
          if (x > dividend) return (n-1);
          return div_loop(x+divisor, n + 1);
        }
      }
       
      

      【讨论】:

      • 引用问题描述:“赋值只需要一个函数,所以它不是正确答案。”
      • 该赋值要求只能输入2个变量和一个函数。
      【解决方案5】:

      您唯一的问题是,当您使用 n2 = n2 + con 时,您仍然在第二种方法中比较 n1 和 n2,而 con 仍然是您的凝视 n2,它应该可以工作。

          private int div(int n1, int n2)
          {
              if (n1 == n2) return 1;
              if (n1 < n2) return 0;
              return div(n1, n2, n2+n2) + 1;  
          }
          private int div(int n1, int n2, int runner)
          {
              if (n1 == runner) return 1;
              if (n1 < runner) return 0;
              return div(n1, n2, runner+n2) + 1;
          }
      

      【讨论】:

      • 赋值的一个限制是函数“只有2个变量”(参数)。
      猜你喜欢
      • 2015-01-02
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 2021-05-29
      • 1970-01-01
      • 2020-12-17
      • 2023-03-31
      相关资源
      最近更新 更多