【问题标题】:How to write a controllable random number generator?如何编写一个可控的随机数发生器?
【发布时间】:2023-03-04 11:06:01
【问题描述】:

我希望随机数的生成可以通过变量进行控制。例如,如果我说 100,则应以最大随机性生成数字,如果我说 50,则数字不应“随机”。如果我说“0”,则可能随机数根本不应该是随机的 - 可能生成的所有数字都是相同的。

知道我可以用什么来生成这样的受控随机数吗?知道某些 C++ 内置库或 Boost 库是否可以这样做吗?

如果有一种方法可以重新生成相同的随机数序列,那将是很好的选择,因此有一种方法可以为生成器提供种子。

【问题讨论】:

  • 1) 学习一些概率论,这样你就知道如何提出正确的问题; 2) 查看<random> 标头以获得有用的标准库函数。
  • 可能相关的stackoverflow.com/q/2393899/10468 在这里我询问有关引入受控数量的相关性以及随机序列在随机性方面是否“过于完美”。

标签: c++ boost random


【解决方案1】:

您描述您的要求的方式似乎表明使用正态分布(又名高斯分布)可能是可行的方法。它有两个参数:均值和标准差。如果您将标准差设置得非常低,您会得到可能非常接近平均值的随机值。如果将其设置为较大的值,则它们会分布得更广泛。

在 C++11 中,标准库提供了正态分布。如果 C++11 不适合您,那么 Boost 库也有。

下面是一些示例代码:

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
#include <iomanip>

int main()
{
  std::random_device rd;
  std::mt19937 gen(rd());

  std::cout << std::fixed << std::setprecision(3);

  /* Mean 5, standard deviation very low (0.002): */
  std::normal_distribution<> d1(5,0.002);
  for (int i = 0 ; i < 20 ; ++i)
    std::cout << std::setw(7) << d1(gen) << "  ";
  std::cout << std::endl;

  /* Mean 5, standard deviation relatively high (2.0): */
  std::normal_distribution<> d2(5,2);
  for (int i = 0 ; i < 20 ; ++i)
    std::cout << std::setw(7) << d2(gen) << "  ";
  std::cout << std::endl;

  return 0;
}

这是输出:

4.998    5.003    5.001    5.002    5.001    5.001    4.998    5.000    4.999    5.001    5.000    5.003    4.999    5.000    5.001    4.998    5.000    4.999    4.996    5.001  
2.781    3.795    5.669   -0.109    7.831    3.302    3.823    4.439    4.672    4.461    6.626    5.139    6.882    5.406    6.526    5.831    6.759    2.627    3.918    4.617

如您所见,第一行中的所有数字都非常接近 5(即,用您的措辞,“随机性”很低),而第二行中的数字分布得更广。

(编辑:当然,这些数字的 随机性 并没有真正受到影响。只是标准差参数使这些值更有可能以更小(stddev 低)或更宽的形式出现(stddev 高)数字范围。)

【讨论】:

    【解决方案2】:

    提升 has a library 以完全按照您的意愿行事。关注this link到boost教程页面,教你如何做数值分布。

    【讨论】:

      【解决方案3】:

      这个XKCD有点意思;你可能想沉思一会儿。真的没有“随机数”这样的东西,就像没有"an uninteresting number"这样的东西。

      您可以要求的是满足某些测试的一系列数字;例如,在任何子序列中,每个值的频率将大致相同,或者序列中的数字与其后继数字之间没有相关性。这些测试并不能证明序列是“随机的”;只是它可能代表其他此类序列;可能出现在现实世界中的序列,除非受到un-, sub-, or super-natural forces 的限制。

      在 Rosencrantz 和 Guildenstern 的简单掷硬币序列中,很容易看出有偏见的分布会引起怀疑,甚至是存在主义的怀疑。但是假设硬币翻转已经完全平衡:正面,反面,正面,反面,正面,反面,正面,反面,如此穿过喀尔巴阡山峰。这或多或少是随机的?正如 R(或 G)所说,“讨论”。

      【讨论】:

        【解决方案4】:

        首先生成一个随机的位序列。

        当旋钮为 100 时,不要理会序列。

        当旋钮为 50 时,强制每隔一位为 1。

        当旋钮为0时,强制每一位为1。

        [更新,详细]

        这个建议并不像听起来那么随意。

        真正随机的数据源的每一位数据都有一位熵。如果你想要一半的熵率——即每两位数据有一位熵——你可以将每隔一位设置为 1。如果你想要 1/3 的熵——即每两位数据一位熵三位数据——您可以将三位中的每两位设置为 1。以此类推。

        “每比特数据的熵比特”是一个非常合理的定义,用于描述一个数字序列的随机性......当三分之二是随机的而其他比特是随机的时,将序列称为“66% 随机”固定是一个很自然的定义。

        【讨论】:

        • 是的,这是一个很好的答案 (+1)。与我的答案(讨论如何生成完全随机序列,但使用越来越不均匀的概率分布)不同,这个答案试图认真对待随机性的概念.
        【解决方案5】:

        可能最简单的解决方案是在 C++ 中使用 srand 和 rand,两者都使用伪随机性,srand 中的种子值越大,rand 生成的随机数中出现模式所需的时间就越长。

        编辑:

        http://www.cplusplus.com/reference/clibrary/cstdlib/srand/

        【讨论】:

          【解决方案6】:
          r1 = Mathf.PingPong(Mathf.PerlinNoise(map,23)*5+map*.01, 1);
          

          map 是随机种子,一个整数,ping-pong 会反弹 0 到 1 之间的所有值,Perlin 噪声会产生某种噪声,通过向其添加多个 map 来平衡 0 到 1 之间的噪声。

          【讨论】:

            猜你喜欢
            • 2013-01-30
            • 2019-12-15
            相关资源
            最近更新 更多