概率/随机数算法

0-1等概率问题

问题描述

  • 一个随机数产生器以概率P生成0,以概率(1-P)生成1,怎样生成等概率的0和1?

主要思路

  • 如果用这个产生器产生两个位,出现00的概率为P^2,出现01的概率为P(1-P),出现10的概率为P(1-P),而出现11的概率为(1-P)^2。故而可以用10表示1,01表示0,从而保证生成0和1的概率是相同的。

代码实现

int generate01(int (*func)()) {
    if (func == NULL)
        return -1;

    int num1 = -1;
    int num2 = -1;
    int ret = -1;

    while(num1 != num2){
        num1 = func();
        num2 = func();

        if (num1 == 1 && num2 == 0) {
            ret = 1;
            break;

        } else if (num1 == 0 && num2 == 1) {
            ret = 0;
            break;
        }
    }

    return ret;

}

0-1问题扩展

  • 利用这个随机数生成器,等概率的生成1,2,……,n

主要思路

  • 利用上面实现的等概率生成0-1的生成器,等概率的生成k为二进制的bit,而其表示的整数值X在0~n-1的范围时,输出X+1,否则重复产生。

代码实现

int generateRandomNum(int max) {
    if (max < 1) {
        return -1;

    }
    int bit_num = 0, i = 0;

    int result = 0;

    while((0x01 << bit_num) < max)
        ++bit_num;

    //while(result > n) {
        while(bit_num > i) {
            if (generate01())
                result |= 0x01 <<bit_num; //result |= 0x01<<i
            i++;
        }
        i = 0;
   // }

    return result;

}

不重复随机数的产生

问题描述

  • 随机产生0~n-1中的k个不重复的随机数。

主要思路

  • 借用蓄水池算法。先定义一个1~n-1的数组,然后从中抽样K个数。

生成给定范围的随机数

问题描述

  • 给定能随机生成整数1~5的函数,写出能随机生成整数1~7的函数

解决思路

  • 产生K个数(k>1),假定产生的数分别为N1,N2,……Nk,则产生的数为:N1-1+(N2-1)*5 + (N3-1)*5^2,……,(Nk-1)*5^(k-1),即产生的数位于(0,5^(k-1))区间呢。然后把区间等分成k分,则产生的随机数位于(0~6),然后+1即可。如果位于K等分的余数范围,则重新执行上述过程。(PS:不用担心余数问题,当K取3时,落到余数范围的概率已经降为6/125,而且余数不会导致概率的问题,只会影响效率。次解法相当于五进制)

代码实现

int generateRandom(int n) {
    if (n < 1)
        return -1;

    unsigned long long result = 0;

    for (int i = 0; i < n; i++) {
        result += rand5();
    }
    result /= 5;

    return result;
}

如何随机选取1000个关键字

问题描述

  • 给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字)。如何才能从这个无穷尽的流中随机的选取1000个关键字?

主要思路

  • 利用蓄水池算法。先生成一个大小为1000的数组,将前1000个关键字填入数组中,随后的关键字随机进行交换。

在半径为1的圆中随机选取一点

主要思路

  • 假设圆心(0,0)。在X轴[-1,1],Y轴[-1,1]的正方形内随机选点,然后判断该点是否在圆内。正方形的面积为4,圆形的面积为Pi,故而正方形内的随机点落在圆内的概率为: Pi/4

代码实现

void generatePoint(double*x, double *y, int r){
    int base = 10000;

    while (pow(*x, 2) + pow(*y, 2) > pow(r, 2)) {
        *x = random() % 10000;

        *y = random() % 10000;
        *x = (2 * r / (*x)) - r;

        *y = (2 * r / (*y)) - r;
    }
}

蓄水池算法

问题描述

  • 从N个数中,随机抽取K个,是的每个数的抽取概率相同,并且事先不知道K的值

主要思想:

  • 保持一个集合(这个集合中的每个数字出现),作为蓄水池,依次遍历所有数据的时候以一定概率替换这个蓄水池中的数字。将前K个元素都放到水库中,然后对之后的第i个元素,以k/i的概率替换掉这个水库中的某一个元素。

方法证明:

  1. 初始情况。水库中k个元素的出现概率都一致,都是1。
  2. 第一步:处理第k+1个元素。分两种情况:① 元素全部都没有替换;② 其中某个元素被k+1元素替换。
    • 对于case ②:第k+1个元素被选中的概率是k/(k+1),故而这个新元素在水库中出现的概率就一定是k/(k+1)。而水库中剩余的元素出现的概率也就是1-P(P为元素被替换的概率)。水库中任意一个元素被替换的概率为:(k/k+1) * (1/k) = 1/(k+1)。而旧元素出现的概率为k/k+1。即旧元素和新元素出现的概率是相等的。
    • 对于case①:当没有元素被替换时,每个元素出现的概率是一样的。具体为:1-P(P为第k+1个元素被选中) = 1 - k/(k+1) = 1/(k+1)
  3. 利用归纳法:
    • 对于第k+i个元素,其中i ∈(0, length-k)。其出现在水库中的概率为k/(k+i)。利用上面的两步可以得出结论。

算法实现:

int impounding_reservoir(int *array,int length, int k) {
    if (k <= 0 || array == NULL
        || length <= 0 || k > length) {
        return 0;
    }   

    int result[k];
    int i = 0, j = 0;
    srand((unsigned) time(NULL));

    for (i = 0; i < k; i++) {
        result[i] = array[i];
    }   

    for (i = k; i < length; i++) {
        j = random() % length;
        if(j < k)
            result[j] = array[i];
    }   

    for (i = 0; i < k; i++)
        printf("%d ", result[i]);
    printf("\n");

    return k;
}

产生1~400范围内不重复的20个随机数

int * generateRandom(int *array, int num, int start, int end)
{
    int size = end / 32 + end % 32 > 0 ? 1: 0;

    int tmp_arr[size] = {0};

    int index = 1, count = 0;

    srand(time(NULL));

    while(count < num){

        index += rand() ;
        index %= 400 + 1;

        if (test_bit(tmp_arr, index)) {
            continue;
        } else {
            set_bit(tmp_arr, index);
            array[count] = index;
            index = 1;
            count++;
        }
    }
    return array;

}

概率/随机数算法,布布扣,bubuko.com

时间: 2024-11-10 01:09:05

概率/随机数算法的相关文章

C语言生成32位和64位随机数算法

C语言生成32位和64位随机数算法 /** * randstd.h * * Standard definitions and types, Bob Jenkins * * 2015-01-19: revised by cheungmine */ #ifndef _RANDSTD_H__ #define _RANDSTD_H__ #ifndef STDIO # include <stdio.h> # define STDIO #endif #ifndef STDDEF # include <

【Java】揭秘如何利用不等概率随机数制作十赌九骗的赌大小游戏,请不要沉迷各种游戏

上次在<[Java]在一定的范围内产生不同的随机数>(点击打开链接)中说明了如何产生随机数,然后还说了如何在一定的范围内产生不同的随机数,但是这些都是等概率产生随机的问题.等概率在正常情况下,更应该说是学术上是够用了,但是在现实生活中,尤其在现在游戏必须打黄赌毒的擦边球吸引人的大背景下,等概率产生随机数是远远不够用的.你作为游戏商家,说得难听点就是庄家,肯定要不等概率产生随机数来圈玩家的钱.比如,合成装备就你就不能让它合成成功是50%,合成不成功是50%,你必须把合成成功设置为1%甚至更小.这

一亿个不重复的随机数算法

最近浏览“程序员论坛”时发现不少好帖,增长了不少知识,现拿其中一则为例与大家共同分享心得. 某人提出一个问题:怎样才能生成一亿个不重复的随机数? 问题表述起来很简单,似乎只要弄明白什么叫随机数以及怎样用电脑生成随机数,就能解决问题. 随机数,个人理解为一定范围内出现的毫无规律的数,比如扔一个骰子,落在桌面上时朝上的一面所表示的数就是随机数,这个数只能在1到6的范围内,但具体是什么数,谁也不能肯定,因为它没有规律.一组不重复的随机数,对扔骰子来说就是扔出六个不一样的数来,再比如洗一次扑克牌,洗完后

Redis源码分析(二十三)--- CRC循环冗余算法和RAND随机数算法

今天开始研究Redis源码中的一些工具类的代码实现,工具类在任何语言中,实现的算法原理应该都是一样的,所以可以借此机会学习一下一些比较经典的算法.比如说我今天看的Crc循环冗余校验算法和rand随机数产生算法. CRC算法全称循环冗余校验算法.CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去.在接收端, 则根据信息码和CRC码之间所遵循的规则进

随机数算法

伪随机数: 数学公式:r[i]=(v*r[i-1] + u) mod base p=r[i]/base 代码实现 package mytest; public class MyRandom { /** * r[i]=(v*r[i-1] + u) mod base * p=r[i]/base * @param r */ static double random(double[] r){ double temp1,temp2,temp3,base,u,v,p; base=256.0; u=17; v

scala版本的梅森旋转随机数算法

package xzxz import scala.annotation.tailrec class MersenneTwister(seed: Int) { private val SIZE: Int = 624 private val PERIOD: Int = 397 private val DIFF: Int = SIZE - PERIOD private def isOdd(n: Int): Int = n & 1 private def m32(n: Int): Int = 0x80

【微信开发】PHP中奖概率经典算法实例

$arr=array("50","30","20"); //这里简单列出三个数 $pro = array_sum($arr); // 概率数组的总精度 foreach ($arr as $key=>$value){ $randnum = mt_rand(1,$pro); if($randnum<=$value){ $res = $value; //这里是中奖的时候,一般$res会赋值和其概率相对应的奖品 break; }else {

HDU - 4712 Hamming Distance(坑爹的随机数算法 + 暴力求解)

Hamming Distance Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 1728    Accepted Submission(s): 680 Problem Description (From wikipedia) For binary strings a and b the Hamming distance is equa

**PHP随机数算法

<?php $tmp = range(1,30);print_r(array_rand($tmp,10));?> 输出: Array( [0] => 6 [1] => 8 [2] => 13 [3] => 16 [4] => 17 [5] => 20 [6] => 21 [7] => 22 [8] => 28 [9] => 29) ----------------------------------------- 参考: 无论是Web