【问题标题】:how to generate random values with uniform intervals in c within a set range如何在设定范围内在c中生成具有均匀间隔的随机值
【发布时间】:2015-02-03 16:15:47
【问题描述】:

到目前为止,我有一个函数可以在固定范围(最小值,最大值)内生成一个随机整数值,它似乎可以工作。但是,如果我的范围是 (0,100),我怎样才能做到,返回的随机值总是 8 的倍数? (即均匀间隔)

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;
}

下面的代码也是如此。每次调用时,如何使 RANDOM_NUM 变量始终为 20/3 的倍数? 这会生成一个介于 0 和 1 之间的随机浮点值。(即均匀间隔)

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

【问题讨论】:

  • 0 到 100,8 的倍数。嗯,12.5 间隔。
  • Max-Min+1 的一个潜在问题是结果可能很容易溢出。
  • 注意:((float)rand()/(float)(RAND_MAX+1)) 可能会生成 0.0,但不会生成 1.0。 IOWs [0.0, 1.0) - 不完全是“0 到 1 之间的值”。

标签: c random intervals uniform


【解决方案1】:

但是,如果我的范围是 (0,100),我怎样才能使它返回的随机值始终是 8 的倍数?

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

【讨论】:

    【解决方案2】:

    “如何让RANDOM_NUM 变量在我每次调用时始终是 20/3 的倍数?”

    我使用double 而不是float,因为它的精度更高,但即使如此,也不能保证精确的倍数,正如这个程序所示。在测试时,在某些情况下余数为 0,在其他情况下显然是,并且 荒谬 6.666667,即 20/3。这是因为并非所有数字都可以用浮点格式精确表示。

    在小数点表示法中,除法 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;
    }
    

    程序输出(随机数,余数):

    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
    

    【讨论】:

      【解决方案3】:

      假设 rand 是 0 到 100 之间的随机整数:

      rand = rand - (rand % 8);

      【讨论】:

        【解决方案4】:

        最快的解决方案是将整数的最低三个位设置为零:rand &amp;= ~0x07。 (假设rand是0到100之间的整数)

        当然,如果您希望它是不是 2 次幂的数字的倍数,并且如果您不熟悉位操作(注释不会有任何伤害)则很难阅读。

        【讨论】:

          【解决方案5】:

          您可以得到一个 0-13 范围内的随机数,然后将结果乘以 8。它将在 [0, 104] 范围内。你可以为 20/3 做同样的事情。假设您只取整数结果,这似乎是正确的,这将始终有效。

          【讨论】:

            猜你喜欢
            • 2010-10-01
            • 2010-09-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多