我试图随机选择例如4个数字。我需要比较这两种算法的概率。
1#
int a = random.Next(0, 4);
if (a = 0)
statement1
if (a = 1)
statement2
if (a = 2)
statement3
if (a = 3)
statement4
2#
int a = random.Next(0, 1000)
if (a < 250)
statement1
if (a >= 250 && a < 500)
statement2
if (a >= 500 && a < 750)
statement3
if (a >= 750)
statement4
如果我认为它是相同的,我是对的吗?第一个代码中statement1的概率是1/4,第二个代码中的概率是250/1000,所以它也是1/4。但有人告诉我,当我使用更大范围的随机数时,如代码2#,它在统计上更准确。我已经制作了多次重复这些代码的项目,但我不确定它能给我看一些结果。
答案 0 :(得分:3)
它们完全相同(除了第一个不能编译因为在if子句中使用=
而不是==
)。
要证明这一点,请查看Random.Next(int, int)
的实现。根据您的值,Random.Next(0, 4)
是
(int) (Random.Sample() * 4)
和
Random.Next(0, 1000)
是
(int) (Random.Sample() * 1000)
,其中Random.Sample()
是一个返回随机双精度的私有方法。
现在应该很容易看到,当Random.Next(0, 4)
返回0到250之间的数字时,Random.Next(0, 1000)
将返回0 。
答案 1 :(得分:2)
无论范围是什么,伪随机数应均匀分布。如果在第二个示例中,如果您只选择最后4位(a & 3
),则会获得与(a>>2) & 3
选择下一个4位相同的分布。即你在第二个例子中使用范围在算法上做的是丢弃随机生成器给你的很多信息。你不再拥有更大范围的“随机性”。
话虽如此,伪随机生成器确实有它们的特质,但除非你认真对待它,否则不值得担心!
答案 2 :(得分:0)
分布是统一的,很容易验证:
public class Program
{
static void Main(string[] args)
{
var random = new Random();
const int iterations = 10000000;
var hits1 = 1.0 * Enumerable.Range(1, iterations)
.Select(i => random.Next(0, 4))
.Where(i => i == 0).Count();
Console.WriteLine(hits1 / iterations);
var hits2 = 1.0 * Enumerable.Range(1, iterations)
.Select(i => random.Next(0, 1000))
.Where(i => i < 250)
.Count();
Console.WriteLine(hits2 / iterations);
}
}
答案 3 :(得分:-1)
我的测试如下
在10K循环中,使用范围1-4
和范围1-1000
进行2次测试,结果为
1-4
1 > 2484 times
2 > 2519 times
3 > 2511 times
4 > 2487 times
0 - 1000
1 - 250 > 2421 times
250 - 500 > 2531 times
500 - 750 > 2529 times
750 - 1000 > 2490 times
我的结论是,它们没有任何区别,你必须进入矩阵等等,以控制随机数生成等等。
注意:我的测试是使用PHP完成的,源代码如下。
<?php
$first = array(1=>0,2=>0,3=>0,4=>0);
$second = array('0 - 250' => 0, '250 - 500' => 0, '500 - 750' => 0,'750 - 1000' => 0);
for($i=0;$i<=10000;$i++) //10K
{
//First
$f_number = rand(1,4);
switch($f_number)
{
case 1: $first[$f_number]++; break;
case 2: $first[$f_number]++; break;
case 3: $first[$f_number]++; break;
case 4: $first[$f_number]++; break;
}
//Second
$s_number = rand(1,1000);
if($s_number < 250) $second['0 - 250']++;
if($s_number > 250 && $s_number < 500) $second['250 - 500']++;
if($s_number > 500 && $s_number < 750) $second['500 - 750']++;
if($s_number > 750) $second['750 - 1000']++;
}
var_dump($first,$second);
?>