【问题标题】:Compute x/y without Arithmetical Operators不使用算术运算符计算 x/y
【发布时间】:2019-12-30 12:43:59
【问题描述】:

我目前正在使用 python 中的“编程面试要素”,并且在这部分卡住了。下面的代码只是简单地将两个数字相乘而不使用任何运算符;作者给出的解释如下:

我们可以计算出最大的 k 使得 (2^k)y 11。我们从 (1011) 中减去 (1000) 得到 (11),加上 2^k = 2^ 2 = (100) 到商, 并继续将 x 更新为 (11)。

在每次迭代中找到最大 k 的更好方法是识别 它一直在减少。因此,而不是在每个测试 迭代 (2^0)y, (2^1)y, (2^2)y, ... 是否小于或等于 x,在我们最初找到满足 (2^k)y

def divide(x, y):

    result, power = 0, 32
    y_power = y << power

    while x >= y:

        while y_power > x:

            y_power >>= 1
            power -= 1

        result += 1 << power
        x -= y_power

    return result

我的问题是:

  1. 算法的工作原理(概述)
  2. whey do power = 32
  3. 我们为什么要通过幂来移动 y (32)
  4. y_power 代表什么
  5. 我们为什么要加 1

【问题讨论】:

    标签: python algorithm binary bit-manipulation bitwise-operators


    【解决方案1】:

    这是二进制数的长除法。你可能在学校里学过十进制数。

    如果我们想将x 除以y,我们会问自己“如果我们向其添加尽可能多的零,yx 匹配多少次?”。将 n 个零添加到 y 相当于乘以 2^n 或左移 n。

    power = 32
    y_power = y << power
    

    算法的第一个猜测是在y 中添加 32 个零,即向左移动 power。因此,如果您知道您的结果可能 >= 2^33,您将不得不为 power 使用更大的初始值。

    while y_power > x:
       y_power >>= 1
       power -= 1
    

    在内部循环中,它将测试y_power 是否已经适合x,如果不适合,将“将其向右移动一位”。

    result += 1 << power
    

    完成后,它只会将“y 左移多少次适合 x”写入结果。与二进制数一样,这可以是零或一,并且内部循环跳过所有零,这必须是一。

    x -= y_power
    

    正如您从长除法中知道的那样,我们现在需要从被除数中减去除数的倍数 y,然后继续得到结果。

    while x >= y:
    

    如果这个差值 y 小于 x,我们将停止,因此 2^power * y 不可能适合 x

    示例 让我们计算一下 15/5:

     1111 / 101 = 11
    -1010
    ------
      101
     -101
    ------
        0
    

    我们有x=1111 和y=101 并以power=1 开头为简洁起见。首先我们计算y_power = y&lt;&lt;power = 101&lt;&lt;1 = 1010。由于1010 &gt; 1111 为假,我们跳过内部循环并将1&lt;&lt;power = 1&lt;&lt;1 = 10 添加到结果中。然后我们从x = 1111 中减去y_power = 1010 得到101。现在y_power = 1010 &gt; 101 = x 为真,我们递减power,所以我们得到power = 0y_power = y&lt;&lt;power = 101。现在y_power&gt;x再次为假,我们将1&lt;&lt;power = 1添加到我们的结果中并得到x - y_power = 0。现在x &gt;= y 是假的,我们完成了result = 11

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-12
      • 2021-11-09
      • 2019-06-06
      • 2022-01-07
      • 1970-01-01
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多