PHP - 改进随机数序列生成

标签 php random numbers

我想这是我关于 SO 的第一个问题。

我目前正在一个网站上工作,我必须为彩票生成 1 到 29 之间的 6 个数字(每个最大值之一)。由于它们可以按任何顺序排列,因此我只是在之后对它们进行排序。

如果我没记错的话,应该是(29*28*27*26*25*24)/6! = 475020 不同的可能组合。

我尝试了不同的生成序列的方法,使用 mt_rand 或 random_int(来自 random_compat )但是当我用大约 10k 次迭代测试它时,我总是得到大约 100 个重复项,即使它们是 465k 组合仍然可用。

以下是我一直在尝试的代码示例:

// Using an array and mt_rand (or random_int, giving same results)
// Also tried shuffling the array instead of simply reindexing it, not better

$values = range(1, 29);

while(count($values) > 6) {
    unset($values[mt_rand(0, count($values) - 1)]);
    $values = array_values($values);
}



// Creating the array from random numbers (same results using random_int)

$values = array();
while (count($values) < 6) {
    $r = mt_rand(1, 29);
    if (in_array($r, $values)) {
        continue;
    } else {
        $values[] = $r;
    }
}

很好...我的问题是:

  • 有没有办法改进我目前正在做的事情?
  • 事情会这样吗,我必须处理它?<​​/li>
  • 我是不是做错了?

谢谢!

琳。

PS: 翻了很多问题,没找到满足我需求的东西,如果我看的不够好,请见谅!

只是为了说明一些事情:使用 random_int(利用/dev/urandom 或 openssl_random_pseudo_bytes)不会改善任何事情,我认为会。如果可能,我不想使用任何外部 API(如 random.org)。

最佳答案

Using random_int (which makes use of /dev/urandom or openssl_random_pseudo_bytes) doesn't improve anything, which I thought would.

当然可以,只是您无法通过视觉识别。 mt_rand()rand() 只允许大约 232 可能的种子和 232 可能的输出,而且,大多数重要的是,具有确定性序列:if you know a few outputs, you can predict the rest until it's reseeded .

您的操作系统的 CSPRNG 没有任何此类限制。了解一些 random_int() 输出(在 PHP 中,在 32 位系统上限制为 232 可能的值,在 64 位系统上限制为 264 -位系统)不会给你任何关于 future 输出的信息。

I'm currently working on a website and I have to generate 6 numbers between 1 and 29 (one of each max) for a lottery. As they can be in any order, I simply sort them afterwards.

好吧,这是个好主意。你肯定想要一个 CSPRNG。

when I test it with something like 10k iterations, I always get around 100 duplicates, even though they are like 465k combinations still available.

正如其他人所指出的,这是 birthday problem/paradox在玩。

如果您需要解决方案,请尝试以下操作:

function random_unique_select($num, array $possible_values)
{
    $sizeof = count($possible_values);
    if ($num > $sizeof) {
        throw new InvalidArgumentException('$num is too large');
    }
    $selected = [];
    for ($i = 0; $i < $num; ++$i) {
        // Grab a random int [0, ... N - 1]
        $r = random_int(0, $sizeof - 1);
        // Copy the selected value into $selected
        $selected[] = $possible_values[$r];
        // Delete it from the range of possible values
        unset($possible_values[$r]);
        // N has grown smaller by 1
        --$sizeof;
        // Reset keys; we want this to be zero-indexed.
        $possible_values = array_values($possible_values);
    }
    return $selected;
}

$lottery = random_unique_select(6, range(1,29));

演示:

关于PHP - 改进随机数序列生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31825955/

相关文章:

python - 如何将字符串数字转换为列表中的整数?

c# - 如何使用 C# 计算整数的二进制表示中的尾随零

java - 逐行打印数字的递归方法

php - 如何使用 jquery 发布和获取 php 变量?

php - Directus API : how to filter the results

c# - 自定义随机可枚举?

random - 是否可以使用物理传感器生成随机数?

javascript - HTML5 Canvas 随机形状

php - 如何使用php和mysql动态计算经纬度距离?

php - 在 CodeIgniter 中检查 Ajax 请求