小能豆

我应该如何从基于 PRNG 的生成转向基于哈希的程序生成?

py

我想用基于哈希的数据生成器替换现有的基于随机数的数据生成器(在 Python 中),这样它不再需要按顺序生成所有内容,就像这篇文章的启发一样。

我可以通过获取哈希的整数版本并将其除以哈希的最大值来创建一个从 0 到 1 的浮点数。

我可以通过取浮点数并乘以平坦范围来创建一个平坦整数范围。我可能可以使用模数并接受偏差,因为哈希范围很大而我的平坦范围很小。

我如何使用哈希来创建高斯或正态分布的浮点值?

对于所有这些情况,我是否最好仅使用我的哈希作为新 random.Random 对象的种子,并使用该类中的函数来生成我的数字并依靠它们来获得正确的分布特性?

目前,我的代码结构如下:

num_people = randint(1,100)
people = [dict() for x in range(num_people)]
for person in people:
    person['surname'] = choice(surname_list)
    person['forename'] = choice(forename_list)

问题是,为了使给定的种子保持一致,我必须以相同的顺序生成所有人,并且必须先生成姓氏,然后再生成名字。如果我在两者之间添加中间名,那么生成的名字就会改变,所有后续人员的名字也会改变。

我想要像这样构造代码:

h1_groupseed=1

h2_peoplecount=1
h2_people=2

h4_surname=1
h4_forename=2

num_people = pghash([h1_groupseed,h2_peoplecount]).hashint(1,100)
people = [dict() for x in range(num_people)]
for h3_index, person in enumerate(people,1):
    person['surname'] = surname_list[pghash([h1_groupseed,h2_people,h3_index,h4_surname]).hashint(0, num_of_surnames - 1)]
    person['forename'] = forename_list[pghash([h1_groupseed,h2_people,h3_index,h4_forename]).hashint(0, num_of_forenames - 1)]

这将使用传递给 pghash 的值来生成哈希,并使用该哈希以某种方式创建伪随机结果。


阅读 21

收藏
2025-01-01

共1个答案

小能豆

我已经继续为 random.Random 类中的某些函数创建了一个简单的基于哈希的替代方案:

from __future__ import division
import xxhash
from numpy import sqrt, log, sin, cos, pi

def gaussian(u1, u2):
    z1 = sqrt(-2*log(u1))*cos(2*pi*u2)
    z2 = sqrt(-2*log(u1))*sin(2*pi*u2)
    return z1,z2

class pghash:
    def __init__(self, tuple, seed=0, sep=','):
        self.hex = xxhash.xxh64(sep.join(tuple), seed=seed).hexdigest()

    def pgvalue(self):
        return int(self.hex, 16)

    def pghalves(self):
        return self.hex[:8], self.hex[8:]

    def pgvalues(self):
        return int(self.hex[:8], 16), int(self.hex[8:], 16)

    def random(self):
        return self.value() / 2**64

    def randint(self, min, max):
        return int(self.random() * max + min)

    def gauss(self, mu, sigma):
        xx = self.pgvalues()
        uu = [xx[0]/2**32, xx[1]/2**32]
        return gaussian(uu[0],uu[1])[0]

下一步是检查我的代码并用 pghash 对象替换对 random.Random 方法的所有调用。

2025-01-01