How to generate a random integer number from within a range

后端 未结 11 1256
隐瞒了意图╮
隐瞒了意图╮ 2020-11-21 23:57

This is a follow on from a previously posted question:

How to generate a random number in C?

I wish to be able to generate a random number from within a part

11条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-22 00:48

    As said before modulo isn't sufficient because it skews the distribution. Heres my code which masks off bits and uses them to ensure the distribution isn't skewed.

    static uint32_t randomInRange(uint32_t a,uint32_t b) {
        uint32_t v;
        uint32_t range;
        uint32_t upper;
        uint32_t lower;
        uint32_t mask;
    
        if(a == b) {
            return a;
        }
    
        if(a > b) {
            upper = a;
            lower = b;
        } else {
            upper = b;
            lower = a; 
        }
    
        range = upper - lower;
    
        mask = 0;
        //XXX calculate range with log and mask? nah, too lazy :).
        while(1) {
            if(mask >= range) {
                break;
            }
            mask = (mask << 1) | 1;
        }
    
    
        while(1) {
            v = rand() & mask;
            if(v <= range) {
                return lower + v;
            }
        }
    
    }
    

    The following simple code lets you look at the distribution:

    int main() {
    
        unsigned long long int i;
    
    
        unsigned int n = 10;
        unsigned int numbers[n];
    
    
        for (i = 0; i < n; i++) {
            numbers[i] = 0;
        }
    
        for (i = 0 ; i < 10000000 ; i++){
            uint32_t rand = random_in_range(0,n - 1);
            if(rand >= n){
                printf("bug: rand out of range %u\n",(unsigned int)rand);
                return 1;
            }
            numbers[rand] += 1;
        }
    
        for(i = 0; i < n; i++) {
            printf("%u: %u\n",i,numbers[i]);
        }
    
    }
    

提交回复
热议问题