7随机到10随机

已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。

  1. int rand10() {
  2. int n;
  3. do{
  4. n= (rand7()-1)*7+rand7()-1;//生成[0,48]之前的等概率随机数。
  5. }while(n>=40);//筛选出[0,39]内的数,因为要获取[1,10],就要先获取[0,9],就要通过x%10获取,为了使得[0,9]出现等概率,x属于[0,9]/[10,19]/[20,29]均可,为了最容易出数,取最大范围[0,39]
  6. return n%10+1;
  7. }

不等概率随机到等概率随机

image.png

        const float absError = 1e-6;
        bool isEquire(float a, float b) {
            return fabs(a - b) < absError;
        }
        int rand01p() {
            float p = 0.87;//p值任意指定
            float randomGet = ((float)(rand() % 1000)) / 1000;
            return (randomGet < p || isEquire(randomGet, p)) ? 0 : 1;
        }

用rand01p()生成rand1_6(),等概率生成[1,6]内的整数。

因为生成01和10的概率p(1-p)和(1-p)p是相等的,所以先可以等概率产生0或1,即等概率获得[0,1]内的数:

        int random01() {
            int get01;
            do {
                get01 = random01p();
            } while (get01 == random01p());//当两次random的结果不为p(1-p)或(1-p)p时继续
            return get01;//等概率生成0或1
        }

用插空法迭代生成目标范围:(有几个数就扩大几倍插空)

        int random03() {
            return random01() * 2 + random01();//等概率生成[0,3]内的整数。
        }

筛选:

        int random1_6() {
            int randomGet;
            do {
                randomGet = random03() * 4 + random03();//等概率生成[0,15]内的整数。
            } while (randomGet >= 12);
            return randomGet % 6+1;
        }