【问题标题】:too many collisions in random number generator collision test随机数生成器碰撞测试中的碰撞太多
【发布时间】:2026-02-20 20:00:02
【问题描述】:

我预计 lKolizji 变量约为 128,但对于大量生成的数字和“框”来说,它要高得多。较小数字的结果很好。我不知道为什么会这样。这是我的代码,其中包含给出错误答案的示例参数。良好结果的示例(大约 128)是 int lPrzedzialow=1000000; int iLiczb = 16000;

#include <iostream>
#include <gsl/gsl_rng.h>
#include <stdlib.h>
#include<cmath>
#include <algorithm>
using namespace std;
int main (void)
{
//Random number
   unsigned int seed=2596524;
   gsl_rng * r=gsl_rng_alloc (gsl_rng_mt19937);
   gsl_rng_set(r,seed);
   gsl_rng_env_setup();
//Parameters
   int lPrzedzialow=10000000000;//number of boxes
   int iLiczb = 1600000;//number of random numbers
   int z,lKolizji=0;//lKolizji holds collision number
   vector<int> lwKomorkach(iLiczb);//number of boxes of random numbers
   long double dlPrzedzialu=1./(lPrzedzialow);
//number of box of a random number 
   for (int i = 0; i < iLiczb; i++)
   {
       lwKomorkach[i] = floor((gsl_rng_uniform (r)/dlPrzedzialu));
   }
//sorting
   sort( lwKomorkach.begin(), lwKomorkach.end() );
//how many collisions
   for(z=0;z<=iLiczb-1;z++)
   {
       if(lwKomorkach[z+1]==lwKomorkach[z]){lKolizji++;}
   }
  double pdf[lKolizji];
  pdf[0]=exp(-128);
  double spdf=exp(-128);
  for(int h=1;h<lKolizji;h++){
     pdf[h]=pdf[h-1]*128./(h);
     spdf+=pdf[h];
  }
  double pwyzsze=1.-spdf;
  cout<<endl<<lKolizji<<" "<<spdf<<"  "<<pwyzsze<<endl;
  gsl_rng_free (r);
  return 0;
  }

【问题讨论】:

  • 给出一些参数输出示例(“好”案例;“坏”案例)。我希望上面的参数有 254 个。所以也许你可以解释一下你是如何期望 128 的?
  • 好输出:133 0.66 0.34,坏输出:448 1 3*10^(-16)。我们想要 128 的碰撞数。这个 128=n^2/2l 的等式,其中 n 是随机数的数量,l 是周期数。然后 260l=n^2 我们做了一个技巧 l=s^2 16s=n 当 s=1000 然后 l(lPrzedzialow) 是 10^6 和 lLiczb=16*1000=16000。
  • 这里我说的是lPrzedzialowiLiczb的定义。这些是输入,lKolizji 是输出。那么您的评论中的输入在哪里?为什么它不遵循代码的形式/约定?
  • 即使您生成介于 0 和 lPrzedzialow 的截断值之间的 long double 随机值,这些值仍存储在 vectorint 值中,这将量化将long double的全精度结果转化为整数值,熵损失很大。
  • 将向量类型更改为 long long int 会使 sytuation 有所改善,但事实并非如此

标签: c++ for-loop random generator gsl


【解决方案1】:

这个数字:10000000000,对于 32 位 int 来说太大了。事实上,它相当于 1,410,065,408,大约是您认为的大小的 1/7。

【讨论】:

  • 所以我应该使用例如 long long int 吗?然后我的程序在它开始计数之前就崩溃了
  • @Sarah 然后检查你的编译器支持的类型。对于极端情况:总是有GNU MP
  • @Sarah,你可以试试,但要考虑到这个数字越大,你的倒数计算就越不精确,尤其是 long double 可能或可能不等于普通 double取决于您的平台。
  • 我只是尝试了每种类型,它给出了相同的结果或根本不起作用