【问题标题】:Python Decimal to Binary RecursivePython十进制到二进制递归
【发布时间】:2021-12-27 00:38:29
【问题描述】:

我正在编写一个函数,它接受一个参数“n”,它将使用递归公式将十进制数转换为二进制数。

这是我的非递归函数,但我需要弄清楚如何递归地编写它。

def dec2bin(n):
    bStr = ''
    if n < 0:
        return 'Must be a positive integer'
    elif n == 0:
        return '0'
    else:
        bStr += str(n%2)
    return bStr

【问题讨论】:

  • 显而易见,您的非递归函数不起作用。它只是返回“0”或“1”,即。 n 的奇偶校验。它不会进行十进制到二进制的转换。

标签: python python-3.x


【解决方案1】:

想想你的基本情况。将答案直接写入程序对哪些输入有意义? 0? 1?可能仅此而已;你不希望一个巨大的elif 链上升到“好的,如果它是 314,我们可以返回 '100111010'”。想想你需要多少个数字来硬编码答案,作为递归的一种基础,以及你可以并且应该让算法处理哪些数字。

想想你的递归调用。如果您想生成n 的二进制表示,对dec2bin 的调用会得到大部分答案,那么您可以稍微修改一下结果并返回它?好吧,如果n 大于1,则n 的二进制表示是n//2 的二进制表示,后面还有一个数字,就像n 的十进制表示是n//10 后面还有一个数字。

【讨论】:

  • 赞成鼓励提问者思考问题,同时仍提供清晰的路线图。
【解决方案2】:

您的代码几乎没问题。您实际上不必维护bStr。假设您知道n//2 的二进制表示,那么n 的二进制表示是n//20 的二进制表示,如果n 可以被21 整除。

喜欢n = 3n//2 = 1dec2bin(n//2) = '01' 所以dec2bin(n) = '01'+'1'[因为3 不能被2 整除] = '011'

你的代码应该是这样的。

def dec2bin(n):
    if n < 0:
        return 'Must be a positive integer'
    elif n == 0:
        return '0'
    else:
        return dec2bin(n//2) + str(n%2)

就是这样。

【讨论】:

    【解决方案3】:

    这是@Stickysli 对@rnbguy 解决方案的“改进”的后续。正在解决的问题是不必要的前导 0,但以不为零本身产生空结果的方式消除它。提议的“改进”非常复杂(是原始代码行数的两倍多)并且依赖于写入全局变量!

    我相信我们可以使用比原来更少的代码行来解决问题,方法是使用测试来查看我们是否在数字 1 上递归,因为这是问题的根源:

    def dec2bin(n):
        if n < 0:
            raise ValueError("Must be a positive integer")
    
        digit = str(n % 2)
    
        return dec2bin(n // 2) + digit if n > 1 else digit
    

    之后:

    >>> dec2bin(22)
    '10110'
    >>> dec2bin(0)
    '0'
    >>> 
    

    【讨论】:

      【解决方案4】:

      为了改进 rnbguy 的答案,我发现当您的输入是除 0 之外的任何数字时,它实际上返回二进制表示形式,最后带有额外的 '0' .

      要删除它,我想出的唯一解决方案是添加一个全局变量,该变量会记住模 n%2 的先前值:

      prev = 0
      def dec2bin(n):
          global prev
          if n < 0:
              return 'Must be a positive integer'
          elif n == 0:
              if prev == 0:
                  return '0'
              else:
                  prev = 0
                  return ''
          else:
              m = n%2
              prev = m
              return dec2bin(n//2) + str(m)
      

      这背后的原因是当您尝试divmod(0, 2) 时,输出是(0, 0),所以我们知道输出必须是简单的'0'。但是如果我们有一个大于 0 的数字,递归函数将总是结束除法 1//21%2,这将输出与 divmod(1, 2) == (0, 1) 相同的结果。

      为了在我们的输出末尾回避另一个'0',我们将1%21 保存在全局变量prev 中,并在prev != 0 在第二种情况下检查它,因为我们目前有n = 0.

      之前

      >>> print dec2bin(22)
      010110
      >>> print dec2bin(0)
      0
      

      之后

      >>> print dec2bin(22)
      10110
      >>> print dec2bin(0)
      0
      

      请注意,我们必须在return '' 旁边添加prev = 0,否则print dec2bin(0) 将不会输出任何内容,因为最后执行的代码将prev 设置为1

      【讨论】:

        【解决方案5】:

        修改所有答案。

        解决方案 1

        def dec2bin(num):
            if num == 0:
                return "" 
            else:
                return dec2bin(num//2) + str(num%2) 
        

        调用函数为:

        dec2bin(233)
        

        解决方案 2

        def dec2bin(num, result):
            if num == 0:
                return result 
            
            result = str(num % 2) + result
            return dec2bin(num//2, result)
        

        调用函数为:

        dec2bin(233, "")
        

        【讨论】: