【问题标题】:Python unsigned integers operations like C [duplicate]Python无符号整数运算,如C [重复]
【发布时间】:2022-02-02 22:46:14
【问题描述】:
import ctypes

def main():
    
    key = 0xDEADBEEF
    
    print(f"({type(key)})  {key = }")
    key = key * 5 + 2
    print(f"({type(key)})  {key = }")
    key = key * 5 + 2
    print(f"({type(key)})  {key = }")
    key = key * 5 + 2
    print(f"({type(key)})  {key = }")
    
    key = ctypes.c_uint(0xDEADBEEF)
    
    print(f"({type(key)})  {key.value = }")
    key = ctypes.c_uint(key.value * 5 + 2)
    print(f"({type(key)})  {key.value = }")
    key = ctypes.c_uint(key.value * 5 + 2)
    print(f"({type(key)})  {key.value = }")
    key = ctypes.c_uint(key.value * 5 + 2)
    print(f"({type(key)})  {key.value = }")


if __name__ == '__main__':
    main()

如果你运行它,它会输出:

(<class 'int'>)  key = 3735928559
(<class 'int'>)  key = 18679642797
(<class 'int'>)  key = 93398213987
(<class 'int'>)  key = 466991069937
(<class 'ctypes.c_ulong'>)  key.value = 3735928559
(<class 'ctypes.c_ulong'>)  key.value = 1499773613
(<class 'ctypes.c_ulong'>)  key.value = 3203900771
(<class 'ctypes.c_ulong'>)  key.value = 3134601969

为什么它在 python 上不断增长?

有没有什么方法可以在不使用 ctypes 的情况下复制 C 的功能,或者它只是 python 的工作原理?

编辑:

好的,感谢@n.1.8e9-where's-my-sharem,我了解到在 C 语言中 uint get 的上限为 32 位,为了在 python 中获得同样的效果,我们可以使用 number modulo 2^32



def main():
    key_a = 0xDEADBEEF
    key_b = uint32(0xDEADBEEF)
    printBinary(key_a)
    printBinary(key_b)
    print('--')
    key_a = key_a * 5 + 2
    key_b = uint32(key_b * 5 + 2)
    printBinary(key_a)
    printBinary(key_b)
    print('--')
    key_a = key_a * 5 + 2
    key_b = uint32(key_b * 5 + 2)
    printBinary(key_a)
    printBinary(key_b)
    print('--')
    key_a = key_a * 5 + 2
    key_b = uint32(key_b * 5 + 2)
    printBinary(key_a)
    printBinary(key_b)
    print('--')
    key_a = key_a * 5 + 2
    key_b = uint32(key_b * 5 + 2)
    printBinary(key_a)
    printBinary(key_b)
    

def printBinary(argument) -> None:
    binary_repr = f"{argument:<15} in binary {argument:>43b}"
    print(binary_repr)

def uint32( n, num_bits=32):
    return n % (2 ** num_bits)

if __name__ == '__main__':
    main()

所以如果我们运行之前的代码,我们会得到:


3735928559      in binary            11011110101011011011111011101111
3735928559      in binary            11011110101011011011111011101111
--
18679642797     in binary         10001011001011001001011101010101101
1499773613      in binary             1011001011001001011101010101101
--
93398213987     in binary       1010110111110111101111010010101100011
3203900771      in binary            10111110111101111010010101100011
--
466991069937    in binary     110110010111010110101100011101011110001
3134601969      in binary            10111010110101100011101011110001
--
2334955349687   in binary  100001111110100110001011110010011010110111
2788107959      in binary            10100110001011110010011010110111

我们可以看到,使用函数uint32,我们可以保留密钥的前 32 位。

【问题讨论】:

  • “为什么它在 python 中不断增长?” - 更好的问题是“为什么它在 C 中不断增长?”。跨度>
  • 如果你想要运算模 2^n,也许添加显式减少模 2^n?
  • @n.1.8e9-where's-my-sharem。我对python中的数学运算不是很了解,我只是想在python中复制一个C#程序。
  • @n.1.8e9-where's-my-sharem。好的,所以n % (2 ** num_bits) 有效,num_bits 是 32,因为 uint 是一个 32 位无符号整数,你认为你可以在答案中解释一下以便我接受吗?
  • @n.1.8e9-where's-my-sharem。如果我理解正确,我得到的数字在我的第一种情况下不断增加并且只保留前 32 位?

标签: python c ctypes


【解决方案1】:

Python 整数可以是任意大小(它们是bignums)。在许多其他编程语言中,整数的大小是固定的,并且会溢出/环绕模 2number_of_bits

如果您想在 Python 中复制这些语言的行为,最简单的方法是添加显式减少模 2number_of_bits。有几种等效的方式来表达这种减少:

n = n % (2**nbits)
n = n % (1<<nbits)
n = n & ((1<<nbits) - 1)

【讨论】:

  • 请注意,这样写,表达式(2**nbits)等每次都会被计算。将值存储在变量中会更有效。
猜你喜欢
  • 2015-06-16
  • 2017-09-06
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
相关资源
最近更新 更多