Python中十六进制转字符串格式化转换

3 投票
2 回答
4950 浏览
提问于 2025-04-15 12:48

我以前是用以下方法生成随机字符串的(现在我改用了这个方法)。

key = '%016x' % random.getrandbits(128)

通过这种方式生成的密钥通常是32个字符的字符串,但有一次我得到了31个字符。

我不明白的是:为什么是32个字符,而不是16个? 难道一个十六进制数字不是只需要一个字符来表示吗?

所以如果我要求%016x - 难道不应该得到16个字符,前面可能有零吗?

为什么字符串的长度不总是相同的?

测试案例

import random
import collections
stats = collections.defaultdict(int)
for i in range(1000000):
    key = '%016x' % random.getrandbits(128)
    length = len(key)
    stats[length] += 1

for key in stats:
    print key, ' ', stats[key]

输出:

32   937911
27   1
28   9
29   221
30   3735
31   58123

2 个回答

3

每个十六进制字符从0到F都包含4位信息,也就是半个字节。128位等于16个字节,而打印一个字节需要两个十六进制字符,所以你会得到32个字符。因此,你的格式字符串应该是'%032x',这样总是会生成一个32个字符的字符串,绝不会短。

jkugelman$ cat rand.py
#!/usr/bin/env python

import random
import collections
stats = collections.defaultdict(int)
for i in range(1000000):
    key = '%032x' % random.getrandbits(128)
    length = len(key)
    stats[length] += 1

for key in stats:
    print key, ' ', stats[key]
jkugelman$ python rand.py
32   1000000
6

是的,不过你现在用的格式并不会截断数据。你生成了128个随机位,这通常需要32个十六进制数字来表示。而%016的意思是至少要16个十六进制数字,但它不会自动丢掉多余的数字,因为你需要显示完整的128位数字。那为什么不直接生成64个随机位呢?这样对随机生成器来说工作量更小,而且也不会有格式问题。

顺便说一下,长度有时会是31位,因为每16次中就有1次最高的4位会全是0;实际上,每256次中会有1次最高的8位全是0,这样你就只会得到30位数字,等等。你只要求16位数字,所以格式化会给出大于等于16的最小数字,并且不会进行你没有要求的截断。

撰写回答