C# ";“随机”;double在字典插入上创建可靠的冲突

C# ";“随机”;double在字典插入上创建可靠的冲突,c#,C#,下面的代码片段向字典中添加了随机双精度。我感到惊讶的是,这样做失败了。在20K-50K的插入后,在我的字典中出现女巫碰撞(您的里程可能会有所不同) 这是随机模式,还是导致如此快速重复的哈希? 下面的代码几乎从未运行过。由于散列范围要大得多,我从未想到: var rnd = new Random(); var dict = new Dictionary<double, int>(); for (int i = 0; i< 100000; i++) { var nbr =

下面的代码片段向字典中添加了随机双精度。我感到惊讶的是,这样做失败了。在20K-50K的插入后,在我的字典中出现女巫碰撞(您的里程可能会有所不同)

这是随机模式,还是导致如此快速重复的哈希? 下面的代码几乎从未运行过。由于散列范围要大得多,我从未想到:

var rnd = new Random();
var dict = new Dictionary<double, int>();
for (int i = 0; i< 100000; i++)
{
    var nbr = rnd.NextDouble();
    dict.Add(nbr, i); //fails at some point
}
var rnd=new Random();
var dict=新字典();
对于(int i=0;i<100000;i++)
{
var nbr=rnd.NextDouble();
dict.Add(nbr,i);//在某个点失败
}

使用“随机”会产生碰撞

运行您的代码,但拿出字典,只向列表中添加“random”double,您将看到这很少会在没有冲突的情况下完成

static void Main(string[] args)
{
    var doubles = new List<double>();

    var rnd = new Random();
    for (var i = 0; i < 100000; i++)
    {
        var nbr = rnd.NextDouble();

        if (!doubles.Contains(nbr))
            doubles.Add(nbr);
        else
        {
            Console.WriteLine($"Match");
        }
    }
    Console.WriteLine("Finished");
}
static void Main(字符串[]args)
{
var doubles=新列表();
var rnd=新随机数();
对于(变量i=0;i<100000;i++)
{
var nbr=rnd.NextDouble();
如果(!double.Contains(nbr))
双倍。添加(nbr);
其他的
{
Console.WriteLine($“匹配”);
}
}
控制台。写入线(“完成”);
}

这是由于。Random使用32位种子,从表中可以看出,在生成大约77k的值后,32位空间内发生冲突的概率为50%。

是否有原因不能使用为此目的而创建的GUID?它必须是一个双倍值吗?这只是生日悖论吗?
Random.NextDouble
生成的双倍值实际上是缩放整数,所以范围并不像你想象的那么大。@Rawling-我也这么认为,但对于64位空间,你需要生成约50亿个值才能预期冲突。有关字典中项目数的冲突概率图,请参阅。带有32位散列的100000个项目几乎有100%的冲突几率。种子不相关(大小也不相关),相关的是它一开始只产生不超过2^31个不同的值(因为它只是缩放一个31位整数值,并将结果显示为双精度)。是的,据我记忆所及,种子长度不相关(种子长度可能与伪算法可以创建的不同序列的数量有关)。来源:我大学课程和常识中的一些模糊图像。是的,不是种子,但碰撞概率是给定的。标记为已回答。谢谢大家!