位移右旋

2024-09-27 07:26:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将这个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)))

我在试着摆脱key = 0xf0f0f0f0f123456。当用ror(key, 8 << 1)调用C代码时,它给出000000000f0f0f12,Python给出0x0f0f0f0f0f123456(原始输入!)


Tags: ofreturnvardef解决方案widthlengthgiven
3条回答
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)

你的问题有不同的问题。

C部分:

您使用的key值是64位值(0x0f0f0f0f0f123456),但输出显示编译器的unsigned long只有32位宽。所以C代码所做的是旋转32位值0x0f12345616次,得到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输出完全相同

您的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)

相关问题 更多 >

    热门问题