免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: egmkang
打印 上一主题 下一主题

[算法] 怎么产生n个不重复等概率随机数?? [复制链接]

论坛徽章:
1
射手座
日期:2013-08-21 13:11:46
21 [报告]
发表于 2010-03-01 20:07 |只看该作者
回复 19# A.com

两个数,其中选取一个.
现在已经选了0个,那选取下一个(即最后一个)数,任何一个数出现的概率均是1/2.


正面的反驳我暂时没想到,高中的知识全忘了...汗

论坛徽章:
0
22 [报告]
发表于 2010-03-02 02:41 |只看该作者
本帖最后由 emacsnw 于 2010-03-01 10:44 编辑
... 好像看过的  bit[c];
sum = 0;
v += rand(); 从0 开始循环。 如果bit[v] = 1;
go on, 命中 sum+1;
...
benjiam 发表于 2010-02-28 22:57



    这是所谓的rejection sampling. v+=rand()步进是不需要的,每次都随机选择一个1 .. C中的整数k,检查如果bit[k] = 0就设成bit[k] = 1就可以了。这样的算法适合n << C的情况。当n接近C的时候rejection概率会非常高。算法效率成问题。

论坛徽章:
0
23 [报告]
发表于 2010-03-02 08:20 |只看该作者
回复 14# emacsnw

擦,本来写了准备回复一大版,说明你证明的一个错误,结果发现自己理解错了。这个方法确实好。很恢弘大气的一个方法。佩服。

论坛徽章:
0
24 [报告]
发表于 2010-03-02 08:23 |只看该作者
回复 19# A.com


    等概率的意思是,最终结果上看来,每个数的概率相等。或者弱一点说,多次进行这样的实验,形成k组数,然后每个数站的比率平均。
   从n个数里面选 n个不同数,最终看来,本来每个数被选中的概率就是1.

论坛徽章:
1
射手座
日期:2013-08-21 13:11:46
25 [报告]
发表于 2010-03-02 08:32 |只看该作者
回复 19# A.com

C个数,选取n个,出现某一个数字A的概率是:
1. 第一个数就是A,概率是1/C;第一个数不是A,概率是(C-1)/C;
2. 第二个数是A,概率是(C-1)/C*1/(C-1)=1/C;也不是A的概率是(C-1)/C*(C-2)/(C-1)=(C-2)/C
3. 设第i个数是A的概率是1/C,不是A的概率是(C-i)/C.
    那么第i+1个数是A的概率是:
    (C-i)/C*1/(C-i)=1/C
    不出现A的概率是
    (C-i-1)/C.
4. 下来是那个递归法的后面步骤.....

所以,每一个数字出现A的概率均为1/C,那么选取n个数,出现A的概率就是n/C.

论坛徽章:
0
26 [报告]
发表于 2010-03-02 08:48 |只看该作者
回复 25# egmkang


    这样说明似乎是没错,但是不是精髓。 emacsnw 考虑的时候,根本不是这样考虑的,从c个数中选n个数,
最终的结果,肯定是每个数的概率必须是n/c,这个是不需要说明和任何证明的。因为这是题目等概率的自然要求。
反过来说,我们只要保证,c以概率为n/c选中或者以1-n/c不选中,问题就解决好。很大气的方法。

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
27 [报告]
发表于 2010-03-02 09:22 |只看该作者
其实这个问题是个彻头彻尾的概率问题,并且不难,学点概率论就啥都明白了。

论坛徽章:
1
天秤座
日期:2014-04-27 07:42:20
28 [报告]
发表于 2010-03-02 10:21 |只看该作者
回复  A.com

两个数,其中选取一个.
现在已经选了0个,那选取下一个(即最后一个)数,任何一个数出现的概率 ...
egmkang 发表于 2010-03-01 20:07



   如果你已经选出了一个,那么在选第二个的时候你还有选择么?

论坛徽章:
0
29 [报告]
发表于 2010-03-02 11:28 |只看该作者
本帖最后由 pppStar 于 2010-03-02 11:29 编辑

好贴!

翻译 emacsnw 的算法为C实现以助兴!:)
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <time.h>

  4. static int* parray = NULL;
  5. static int arraysize = 0;

  6. double uniform01()
  7. {
  8.         return ((double) rand() /(double) RAND_MAX) * 1 + 0;
  9. }

  10. void initset(int* pa, int asize)
  11. {
  12.         int i =0;
  13.         for(i = 0;i < asize;i++)
  14.         {
  15.                 pa[i] = 0;
  16.         }
  17. }

  18. void showset(int* pa, int asize)
  19. {
  20.         int i =0;
  21.         for(i = 0;i < asize;i++)
  22.         {
  23.                 printf("%d ", pa[i]);
  24.                 if((i != 0) && ((i+1)%8 == 0))
  25.                 {
  26.                         printf("\n");
  27.                 }
  28.         }

  29.         printf("\n");

  30. }

  31. void addset(int* pa, int asize, int a)
  32. {
  33.         int i =0;
  34.         for(i = 0;i < asize;i++)
  35.         {
  36.                 if(pa[i] == 0)
  37.                 {
  38.                         pa[i] = a;
  39.                         break;
  40.                 }
  41.         }
  42. }

  43. void f(int c, int n)
  44. {
  45.         double u = uniform01();
  46.         int a = 0;

  47.         if(c > 0 && n > 0)
  48.         {
  49.                 if(c == 1 && n == 1)
  50.                 {
  51.                         addset(parray, arraysize, 1);
  52.                 }
  53.                 else
  54.                 {
  55.                         if(u < (double)((n*1.0)/(c*1.0)))
  56.                         {
  57.                                 addset(parray, arraysize, c);
  58.                                 f(c-1, n -1);
  59.                         }
  60.                         else
  61.                         {
  62.                                 f(c-1, n);
  63.                         }
  64.                 }
  65.         }
  66. }

  67. int main(int argc, char* argv[])
  68. {
  69.         int c, n;
  70.         printf("Plaese input C:");
  71.                 scanf("%d",&c);
  72.         printf("\n");

  73.         printf("Plaese input n:");
  74.                 scanf("%d",&n);
  75.         printf("\n");

  76.         parray = (int*)malloc(n*sizeof(int));
  77.         arraysize = n;
  78.         initset(parray, arraysize);
  79.         srand( (unsigned)time( NULL ) );

  80.         f(c,n);

  81.         showset(parray, arraysize);
  82.         free(parray);

  83.         //system("pause");

  84.         return 0;
  85. }
复制代码
附上一些rejection sample的文章,数学真的好难哦
random.rar (967.79 KB, 下载次数: 58)

论坛徽章:
0
30 [报告]
发表于 2010-03-02 14:19 |只看该作者
不重复,等概率?只要事先都不知道数是多少,那么不管你怎么抽都是等概率的。应该就是打乱这个n个数就可以了吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP