Python base64.b32hexencode未创建预期结果

a7qyws3x  于 2023-03-13  发布在  Python
关注(0)|答案(2)|浏览(105)

我希望代码返回TPLIG0作为10亿的base32十六进制扩展值(1.000.000.000),但我得到的是7EDCK00=
下面是我的代码:

import base64
num = 1000000000
needed_bytes = num.to_bytes((num.bit_length() + 7) // 8, byteorder='big')
result = base64.b32hexencode(needed_bytes).decode('utf-8')
print(result)

我尝试了b32hexencodeb32encode以及byteorder='little'byteorder='big',但无法重现预期结果。
如果我用硬编码的数字替换除法:num.to_bytes(5, byteorder='big')我可以得到近似的结果:00TPLIG0。但是这里是怎么回事??
我在Windows上使用python 3.10.7,在Ubuntu上使用3.11.0(两者都创建相同的输出)。

brgchamk

brgchamk1#

num.bit_length() + 7) // 8是4,而不是5。如果不是40位(5字节)的倍数,则b32hexencode=填充其结果,并且这些位被移位。

>>> base64.b32hexencode (bytes([1,2,3,4]))
b'0410610='
>>> base64.b32hexencode (bytes([1,2,3,4,5]))
b'04106105'

使用(num.bit_length() + 39) // 40 * 5以5字节的倍数计算needed_bytes,然后去掉前导零以正确使用base64.b32hexencode()

import base64
num = 1_000_000_000

def convert(n):
    if n == 0:  # b32hexencode() return '=====' for zero, so special handling
        return '0'
    num_bytes = (n.bit_length() + 39) // 40 * 5
    needed_bytes = n.to_bytes(num_bytes, byteorder='big')
    result = base64.b32hexencode(needed_bytes).lstrip(b'0')
    return result.decode() # bytes -> str

def display(n):
    result = convert(n)
    verify = int(result, 32)
    print(f'{result:>9} {verify:17,}')
    
display(num)
for i in range(9):
    n = 2**(i * 5)
    display(n - 1)
    display(n)

输出测试OP值,并滚动每个5位二进制值:

TPLIG0     1,000,000,000
        0                 0
        1                 1
        V                31
       10                32
       VV             1,023
      100             1,024
      VVV            32,767
     1000            32,768
     VVVV         1,048,575
    10000         1,048,576
    VVVVV        33,554,431
   100000        33,554,432
   VVVVVV     1,073,741,823
  1000000     1,073,741,824
  VVVVVVV    34,359,738,367
 10000000    34,359,738,368
 VVVVVVVV 1,099,511,627,775
100000000 1,099,511,627,776
mepcadol

mepcadol2#

您实际上是在尝试将十进制基数转换为base32,我认为base64不适合这种情况。
从一个基数到另一个基数的转换在其他SO答案中已经涉及(例如,参见here),在您的情况下,您可以实现以下函数:

def base10to32(n,symbols="0123456789ABCDEFGHIJKLMNOPQRSTUV"):
    return (base10to32(n//32)+symbols[n%32]).lstrip("0") if n>0 else "0"

base10to32(1000000000)

或者,如果您更喜欢使用现有的模块,numpy可以处理这种类型的转换:

import numpy as np
np.base_repr(1000000000, 32)

输出:

TPLIG0

相关问题