我希望随机数的生成可以通过变量来控制。例如,如果我说 100,则应以最大随机性生成数字,如果我说 50,则数字不应“随机”。如果我说“0”,那么随机数可能根本不应该是随机的——也许生成的所有数字都是相同的。
知道我可以用什么来生成像这样的受控随机数吗?知道是否有一些 C++ 内置库或 Boost 库会这样做吗?
有一种方法来重新生成相同的随机数序列会很好,所以一种为生成器播种的方法也很好。
您描述您的要求的方式似乎表明使用正态分布(又名高斯分布)可能是要走的路。它有两个参数:均值和标准差。如果您将标准偏差设置得非常低,您会得到可能非常接近平均值的随机值。如果将其设置为较大的值,则它们会分布得更广泛。
在 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 高)的数字范围内。)
这个XKCD是有道理的;你可能想沉思一会儿。真的没有“随机数”这样的东西,就像没有“无趣的数”这样的东西。
您可以要求的是满足某些测试的一系列数字;例如,在任何子序列中,每个值的频率将大致相同,或者序列中的数字与其后继数字之间没有相关性。这些测试并不能证明序列是“随机的”;只是它可能代表其他此类序列;也许是现实世界中出现的序列,除非受到非自然力、次自然力或超自然力的限制。
在 Rosencrantz 和 Guildenstern 简单的掷硬币序列中,很容易看出有偏见的分布会引起怀疑,甚至是存在主义的怀疑。但是假设硬币翻转完全平衡:正面,反面,正面,反面,正面,反面,正面,反面,如此穿过喀尔巴阡山峰。这或多或少是随机的?正如 R(或 G)所说,“讨论”。
首先生成一个随机的位序列。
当旋钮位于 100 时,不要理会序列。
当旋钮为 50 时,强制每隔一位为 1。
当旋钮为 0 时,强制每一位为 1。
[更新,详细]
这个建议并不像听起来那么随意。
真正随机的数据源每比特数据有一个熵。如果你想要一半的熵——即每两位数据有一位熵——你可以将每隔一位设置为 1。如果你想要 1/3 的速率——即每两位数据一位熵三位数据——您可以将三位中的每 2 位设置为 1。依此类推。
“每比特数据的熵比特”是一个数字序列随机性的完全合理的定义......并且当三分之二是随机的而其他比特是固定的时,将序列称为“66%随机”是一个很自然的定义。
可能最简单的解决方案是在 C++ 中使用 srand 和 rand,两者都使用伪随机性,srand 中的种子值越大,模式在 rand 生成的随机数中出现的时间就越长。
编辑:
r1 = Mathf.PingPong(Mathf.PerlinNoise(map,23)*5+map*.01, 1);
map 是随机种子,一个整数,ping-pong 会反弹 0 到 1 之间的所有值,Perlin 噪声会产生某种噪声,通过向其添加多个 map 来平衡 0 到 1 之间的噪声。