随机数生成器,x,y坐标作为种子

时间:2016-05-10 02:44:35

标签: algorithm random hash dimension

我正在寻找一个有效的,均匀分布的PRNG,它为平原中的任何整数点生成一个随机整数,坐标x和y作为函数的输入。

int rand(int x, int y)

每次输入相同的坐标时,它必须提供相同的随机数。

您是否知道可用于此类问题的算法以及更高维度的算法?

我已经尝试使用像LFSR这样的普通PRNG,并将x,y坐标合并在一起,将其用作种子值。这样的事情。

int seed = x << 16 | (y & 0xFFFF)

此方法的明显问题是种子不会多次迭代,但会针对每个x,y点再次初始化。如果您想象结果,这会导致非常丑陋的非随机模式。

我已经知道使用某种大小的混乱排列表的方法,如256,你可以得到一个像这样的随机整数。

int r = P[x + P[y & 255] & 255];

但我不想使用这种方法,因为范围非常有限,受限制的时间长度和高内存消耗。

感谢任何有用的建议!

3 个答案:

答案 0 :(得分:3)

我发现了一个基于xxhash算法的非常简单,快速且充足的哈希函数。

gradle extractTpcds

现在它比我上面描述的查找表方法快得多,它看起来同样随机。我不知道随机属性是否与xxhash相比是好的,但只要看起来随机,它就是我公平的解决方案。

这是像素坐标作为输入的样子:

enter image description here

答案 1 :(得分:2)

我的方法

一般来说,我认为你想要一些哈希函数(大多数都是为了输出随机性而设计的; RNG的雪崩效应,明确需要CryptoPRNG的随机性)。与this线程比较。

以下代码使用此方法:

  • 1)从您的输入中构建可以清除的东西
  • 2)哈希 - &gt; random-bytes(非加密)
  • 3)以某种方式将这些随机字节转换为整数范围(难以正确/均匀地执行!)

最后一步是通过this方法完成的,这似乎不是那么快,但具有很强的理论保证(使用了选定的答案)。

我使用的哈希函数支持种子,将在步骤3中使用!

import xxhash
import math
import numpy as np
import matplotlib.pyplot as plt
import time

def rng(a, b, maxExclN=100):
    # preprocessing
    bytes_needed = int(math.ceil(maxExclN / 256.0))
    smallest_power_larger = 2
    while smallest_power_larger < maxExclN:
        smallest_power_larger *= 2

    counter = 0
    while True:
        random_hash = xxhash.xxh32(str((a, b)).encode('utf-8'), seed=counter).digest()
        random_integer = int.from_bytes(random_hash[:bytes_needed], byteorder='little')
        if random_integer < 0:
            counter += 1
            continue # inefficient but safe; could be improved
        random_integer = random_integer % smallest_power_larger
        if random_integer < maxExclN:
            return random_integer
        else:
            counter += 1

test_a = rng(3, 6)
test_b = rng(3, 9)
test_c = rng(3, 6)
print(test_a, test_b, test_c) # OUTPUT: 90 22 90

random_as = np.random.randint(100, size=1000000)
random_bs = np.random.randint(100, size=1000000)

start = time.time()
rands = [rng(*x) for x in zip(random_as, random_bs)]
end = time.time()

plt.hist(rands, bins=100)
plt.show()
print('needed secs: ', end-start)
# OUTPUT: needed secs:  15.056888341903687 -> 0,015056 per sample
# -> possibly heavy-dependence on range of output

可能的改进

  • 从某些来源添加额外的熵(urandom;可以放入str)
  • 创建一个类并进行初始化以记忆预处理(如果每次采样都要花费很多)
  • 处理负整数;也许只是使用abs(x)

假设:

  • 输出范围是[0,N) - &gt;只为其他人转移!
  • 输出范围小于(位)而不是散列输出(可能使用xxh64)

评价为:

检查随机性/均匀性

1D-Histogram of output -> looks good 2D-Representation -> looks good

检查输入是否确定

2D-Representation with equal input-vectors

答案 2 :(得分:1)

您可以使用各种randomness extractors来实现目标。至少有两个来源可以寻找解决方案。

总而言之,您最好使用:

  1. AES-CBC-MAC使用随机密钥(可以修复并重复使用)
  2. HMAC,优选使用SHA2-512
  3. SHA-family哈希函数(SHA1,SHA256等);使用随机的最终块(例如,最后使用大量的随机盐)
  4. 因此,您可以连接坐标,获取其字节,添加随机密钥(对于AES和HMAC)或SHA的盐,并且您的输出具有足够的熵。 根据NIST,输出熵依赖于输入熵:

    假设你使用SHA1;因此 n = 160bits 。我们假设 m = input_entropy (你的坐标&#39;熵)

    • 如果 m&gt; = 2n 则output_entropy = n = 160位
    • 如果 2n&lt; m&lt; = n 然后最大 output_entropy = m (但不保证完整熵)。
    • 如果 m&lt; n 然后最大 output_entropy = m (这是你的情况)

    请参阅NIST sp800-90c(第11页)