简体   繁体   English

如何在设定范围内以均匀的间隔在c中生成随机值

[英]how to generate random values with uniform intervals in c within a set range

So far I have a function which generates a random integer value within a fixed range (Min, Max) and it seems to work. 到目前为止,我有一个函数可以在固定范围内(最小值,最大值)生成一个随机整数值,并且它似乎可以工作。 But how can I make it so that if my range was (0,100), the random values returned is always a multiple of 8? 但是,如果我的范围是(0,100),那么如何使它返回的随机值始终是8的倍数呢? (that is uniform intervals) (即均匀的间隔)

int generate_rand(int Min, int Max)
{
// Generates random number between min and max, inclusive.

int range, result, cutoff;

if (Min >= Max)
    return Min; // only one outcome possible, or invalid parameters
range = Max-Min+1;
cutoff = (RAND_MAX / range) * range;

// Rejection method, to be statistically unbiased.
do {
    result = rand();
} while (result >= cutoff);

return result % range + Min;
}

The same for the code below. 下面的代码相同。 How can I make the RANDOM_NUM variable to always be a multiple of 20/3 every time I call it? 每次调用时,如何使RANDOM_NUM变量始终为20/3的倍数? This one generates a random float value between 0 and 1. (that is uniform intervals) 这会产生一个介于0和1之间的随机浮点值(即均匀的间隔)。

 RANDOM_NUM = ((float)rand()/(float)(RAND_MAX+1));

但是,如果我的范围是(0,100),那么如何使它返回的随机值始终是8的倍数呢?

return ((result % range + Min)/8)*8;

"How can I make the RANDOM_NUM variable to always be a multiple of 20/3 every time I call it?" “如何使每次调用RANDOM_NUM变量始终为20/3的倍数?”

I used double in preference to float due to its greater precision, but even so there cannot be a guarantee of an exact multiple, as this program shows. 由于此程序精度更高,所以我优先使用double来进行float运算,但即使如此,也不能保证精确倍数,如该程序所示。 When tested, in some cases the remainder is 0, in the others it is apparently, and absurdly 6.666667, which is 20/3. 经过测试,在某些情况下,余数为0,在其他情况下,显然为余数, 荒谬的是 6.666667,即20/3。 This is due to the fact that not all numbers can be precisely represented in floating point format. 这是因为并非所有数字都可以用浮点格式精确表示。

In decimal point notation the result of the division 1/3 has a recurrent one digit 0.333333~ which in binary point notation has a recurrent 2 digits 0.010101~~ . 在小数点表示法中,除法1/3的结果具有递归的一位数字0.333333~ ,在二进制点表示法中具有递归的两位数0.010101~~

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define NUMERATOR   20
#define DENOMINATOR 3

double randnum(int numerator, int denominator) {
    return (double)rand() * (double)numerator / (double)denominator;
}

int main(void) {
    int i;
    double random_num, remainder;
    srand ((unsigned)time(NULL));
    for (i=0; i<10; i++) {
        random_num = randnum(NUMERATOR, DENOMINATOR);
        remainder = fmod(random_num, (double)NUMERATOR / (double)DENOMINATOR);
        printf("%-16f %f\n", random_num, remainder);
    }
    return 0;
}

Program output (random number, remainder): 程序输出(随机数,余数):

72706.666667     0.000000
209733.333333    0.000000
170686.666667    6.666667
187546.666667    6.666667
121093.333333    6.666667
116660.000000    6.666667
75646.666667     0.000000
64960.000000     6.666667
186653.333333    0.000000
159713.333333    0.000000

Assuming that rand is your random integer between 0 and 100 : 假设rand是0到100之间的随机整数:

rand = rand - (rand % 8); rand = rand-(rand%8);

The fastest solution would be to just set the three lowest bits of the integer to zero: rand &= ~0x07 . 最快的解决方案是将整数的三个最低位设置为零: rand &= ~0x07 (Assuming that rand is an integer between 0 and 100.) (假设rand是0到100之间的整数。)

Of course that does not apply if you want it to be multiple of a number that is not a power of two and it is hard to read if you're not familiar with bit operations (a comment could not hurt). 当然,如果您希望它是不是2的幂的数字的倍数,那么这将不适用,如果您不熟悉位运算(注释不会受到伤害),则很难阅读。

You could get a random number in the range 0-13 and then multiply your result by 8. It would be in the range [0, 104]. 您可以获取0-13范围内的随机数,然后将结果乘以8。结果将在[0,104]范围内。 You could do the same thing for 20/3. 您可以为20/3做同样的事情。 Assuming you only take integer results, which appears to be true, this would always work. 假设您只取整数结果(看起来是正确的),那么它将始终有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM