【问题标题】:Bitwise Rotate Right按位向右旋转
【发布时间】:2014-11-27 17:38:03
【问题描述】:

我正在尝试将此 C 函数转换为 Python;

typedef unsigned long var;
    /* Bit rotate rightwards */
    var ror(var v,unsigned int bits) {
        return (v>>bits)|(v<<(8*sizeof(var)-bits));
    }

我已经尝试在谷歌上搜索一些解决方案,但我似乎无法让它们中的任何一个给出与此处相同的结果。

这是我从另一个程序中找到的一个解决方案;

def mask1(n):
   """Return a bitmask of length n (suitable for masking against an
      int to coerce the size to a given length)
   """
   if n >= 0:
       return 2**n - 1
   else:
       return 0

def ror(n, rotations=1, width=8):
    """Return a given number of bitwise right rotations of an integer n,
       for a given bit field width.
    """
    rotations %= width
    if rotations < 1:
        return n
    n &= mask1(width)
    return (n >> rotations) | ((n << (8 * width - rotations)))

我正在尝试 btishift key = 0xf0f0f0f0f123456。 C代码在调用时给出000000000f0f0f12ror(key, 8 &lt;&lt; 1) 和 Python 给出; 0x0f0f0f0f0f123456(原始输入!)

【问题讨论】:

  • 那你为什么要传入8 &lt;&lt; 1进行轮换呢?这比 width 大,所以你最终得到 0 次旋转(16 % 8 是 0)。
  • 循环最多 3 个。所以它将旋转为 8 &lt;&lt; 08&lt;&lt;18&lt;&lt;2
  • 所有这些都大于width并且width的倍数,所以rotations %= width将永远是0
  • 我明白这一点。如果我更改 width,我得到的结果仍然无法与 C 输出相比较。
  • C 输出看起来像旋转了 16 位,掩码为 32 位。我完全不知道你为什么在这里使用rotations %= width

标签: python bitwise-operators


【解决方案1】:

您的 C 输出与您提供的函数不匹配。这大概是因为您没有正确打印它。这个程序:

#include <stdio.h>
#include <stdint.h>

uint64_t ror(uint64_t v, unsigned int bits) 
{
    return (v>>bits) | (v<<(8*sizeof(uint64_t)-bits));
}

int main(void)
{
    printf("%llx\n", ror(0x0123456789abcdef, 4));
    printf("%llx\n", ror(0x0123456789abcdef, 8));
    printf("%llx\n", ror(0x0123456789abcdef, 12));
    printf("%llx\n", ror(0x0123456789abcdef, 16));
    return 0;
}

产生以下输出:

f0123456789abcde ef0123456789abcd def0123456789abc cdef0123456789ab

要在 Python 中生成 ror 函数,请参阅这篇优秀的文章:http://www.falatic.com/index.php/108/python-and-bitwise-rotation

此 Python 2 代码产生与上述 C 程序相同的输出:

ror = lambda val, r_bits, max_bits: \
    ((val & (2**max_bits-1)) >> r_bits%max_bits) | \
    (val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))

print "%x" % ror(0x0123456789abcdef, 4, 64)
print "%x" % ror(0x0123456789abcdef, 8, 64)
print "%x" % ror(0x0123456789abcdef, 12, 64)
print "%x" % ror(0x0123456789abcdef, 16, 64)

【讨论】:

    【解决方案2】:

    您的问题存在不同的问题。

    C部分:

    您使用 64 位值 (0x0f0f0f0f0f123456) 的 key 值,但输出显示编译器 unsigned long 仅 32 位宽。所以 C 代码所做的是将 32 位值 0x0f123456 旋转 16 次,得到 0x34560f12

    如果您使用了unsigned long long(假设它在您的架构上是 64 位,就像在我的架构上一样),您将得到 0x34560f0f0f0f0f12(64 位旋转 16 次)

    Python部分:

    mask1和ror之间的宽度定义不一致。 mask1 采用位宽度,其中 ror 采用字节宽度,一个字节 = 8 位。

    ror 函数应该是:

    def ror(n, rotations=1, width=8):
        """Return a given number of bitwise right rotations of an integer n,
           for a given bit field width.
        """
        rotations %= width * 8  #  width bytes give 8*bytes bits
        if rotations < 1:
            return n
        mask = mask1(8 * width)  # store the mask
        n &= mask
        return (n >> rotations) | ((n << (8 * width - rotations)) & mask)  # apply the mask to result
    

    这样key = 0x0f0f0f0f0f123456,你会得到:

    >>> hex(ror(key, 16))
    '0x34560f0f0f0f0f12L'
    >>> hex(ror(key, 16, 4))
    '0x34560f12L'
    

    与 C 输出完全相同

    【讨论】:

      【解决方案3】:

      我在 Python 中找到的最短方法: (注意这仅适用于整数作为输入)

      def ror(n,rotations,width):
          return (2**width-1)&(n>>rotations|n<<(width-rotations))
      

      【讨论】:

        【解决方案4】:

        我知道它快 6 岁了

        我总是发现使用字符串切片比使用位运算更容易。

        def rotate_left(x, n):
            return int(f"{x:032b}"[n:] + f"{x:032b}"[:n], 2)
        
        def rotate_right(x, n):
            return int(f"{x:032b}"[-n:] + f"{x:032b}"[:-n], 2)
        

        【讨论】:

          【解决方案5】:
          def rotation_value(value, rotations, widht=32):
              """ Return a given number of bitwise left or right rotations of an interger 
              value,
              for a given bit field widht.
              if rotations == -rotations:
                  left
              else:
                  right
              """
              if int(rotations) != abs(int(rotations)):
                  rotations = widht + int(rotations)
              return (int(value)<<(widht-(rotations%widht)) | (int(value)>>(rotations%widht))) & ((1<<widht)-1)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-03-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-10
            相关资源
            最近更新 更多