python - 将字符串转换为随机但确定性可重复的均匀概率

标签 python random hashlib

如何转换字符串,例如一个用户 ID 加盐,到一个随机的但实际上是半开放范围 [0.0, 1.0) 中确定性可重复的均匀概率?这means输出 ≥ 0.0 且 < 1.0。无论输入分布如何,输出分布必须均匀。例如,如果输入字符串是 'a3b2Foobar',则输出概率可以重复为 0.40341504。

跨语言和跨平台的算法重现性是可取的。除非有更好的方法,否则我倾向于使用哈希函数。这是我所拥有的:

>>> in_str = 'a3b2Foobar'
>>> (int(hashlib.sha256(in_str.encode()).hexdigest(), 16) % 1e8) / 1e8
0.40341504

我使用的是最新稳定的 Python 3。请注意,这个问题与 convert an integer to a random but deterministically repeatable choice 的相关问题类似但不完全相同。 .

最佳答案

使用哈希

密码散列可能是 [0, MAX_HASH] 范围内均匀分布的整数。因此,它可以通过除以 MAX_HASH + 1 来缩放为 [0, 1) 范围内的 float 。

import hashlib

Hash = hashlib.sha512
MAX_HASH_PLUS_ONE = 2**(Hash().digest_size * 8)

def str_to_probability(in_str):
    """Return a reproducible uniformly random float in the interval [0, 1) for the given string."""
    seed = in_str.encode()
    hash_digest = Hash(seed).digest()
    hash_int = int.from_bytes(hash_digest, 'big')  # Uses explicit byteorder for system-agnostic reproducibility
    return hash_int / MAX_HASH_PLUS_ONE  # Float division

>>> str_to_probability('a3b2Foobar')
0.3659629991207491

这是一个真实的世界usage example .

注意事项:

  • 内置 hash 不能使用方法,因为它可以保留输入的 分布,例如使用 hash(123)。或者,它可以返回在 Python 重新启动时不同的值,例如使用 hash('123')
  • 不必使用模数,因为 float 除法就足够了。

使用随机

random模块可以与 in_str 作为种子一起使用,同时解决围绕 thread safety 的问题和连续性。

使用这种方法,不仅跨语言的可再现性是一个问题,跨多个 future Python 版本的可再现性也可能是一个问题。因此不推荐。

import random

def str_to_probability(in_str):
    """Return a reproducible uniformly random float in the interval [0, 1) for the given seed."""
    return random.Random(in_str).random()

>>> str_to_probability('a3b2Foobar')
0.4662507245848473

关于python - 将字符串转换为随机但确定性可重复的均匀概率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44556105/

相关文章:

Ruby:Random#rand 和 Kernel#rand 之间的区别

python - tf.random.categorical 给出奇怪的结果

python - 用 Python 代码编写的 SHA 512 crypt 输出与 mkpasswd 不同

python - 如何在python中打印大数的所有数字?

java - 无法为二维 boolean 数组赋值

python - 有没有办法将哈希数据从摘要版本转换为十六进制版本

python - 持久化 hashlib 状态

python - 相当于 python3 中的 python2 chr(int)

python - 使用 matplotlib 可视化 10 维数据

python - 将字符串列表 [ '3' , '1' , '2' ] 转换为排序整数列表 [1, 2, 3]