【问题标题】:Generate a random number from 0 to 10000000生成一个从 0 到 10000000 的随机数
【发布时间】:2013-11-21 03:00:15
【问题描述】:

如何生成 0 到 1000000 之间的随机数?

我已经尝试过下面的代码,但它仍然给我从 0 到 32767 (RAND_MAX) 的数字:

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

int main(){
    int i,x;
    srand(time(NULL));
    for(i=0; i<10000; i++){
        int x = rand() % 10000000 + 1;
        printf("%d\n",x);
    }
    return 0;
}

【问题讨论】:

  • 运行上限/RAND_MAX 次并将它们相加?
  • RAND_MAX 通常小于 1000000 是不是像 16000 一样
  • 签出this
  • @Montaldo 将它们加起来不会均匀分布。仅两个制服的总和具有三角形分布。如果您添加的数量超过少数,则总和很快就会达到正态分布。添加 10M/32K = 305 件制服后,95% 的结果将在 5,000,000 +/- 330,000 范围内。

标签: c random numbers


【解决方案1】:

使用这个函数,它会给你两个数字(最小值和最大值)之间的随机数:

unsigned long int my_rand (unsigned long int Min, unsigned long int Max)
{
  static int first = 0;
  if (first == 0)
  {
    srand (time (NULL)); //initialize generator of random number
    first = 1;
  }
  return ((unsigned long int)(rand() * (Max+1 - Min) / RAND_MAX + Min));
}

【讨论】:

    【解决方案2】:

    [编辑] 最初的答案是 0 到 1,000,000。我现在看到它应该是 0 到 10,000,000。

    由于rand() 将给出至少 15 位的答案,因此多次调用rand(),移位 15 并对结果进行异或运算。最后修改 10,000,001。

    unsigned long x;
    x = rand();
    x <<= 15;
    x ^= rand();
    x %= 10000001;
    

    分布非常平坦,但确实引入了非常的偏差。在 32768*32768 次迭代后,x 的每个值从 0 到 10,000,000 发生大约 107.37 次。相反,它们的范围从 107 到 108 次。

    将多个rand() 调用结果与+*| 组合会导致结果分布出现明显偏差。

    [编辑]

    RAND_MAX 是 32767 (0x7FFF) 对于 OP 的平台。 C 规范说“RAND_MAX 宏的值应至少为 32767”。因为 RAND_MAX 可能长于 15 位,所以在其他平台上使用此代码时,使用上面的 ^ 运算符而不是 | 很重要。

    【讨论】:

    • 使用 XOR 会使分布更好吗?
    • @Lưu Vĩnh Phúc 使用 ^保持分发质量 - 不会造成伤害。如果 RAND_MAX > 32767,使用 +| 会使分布更差。
    【解决方案3】:

    如果您想要介于 0 和 1000000 之间的数字,请使用 % 1000001 进行计算。 还保证RAND_MAX 至少为 32767

    int main(){
      int i, x;
      srand(time(NULL));
      for(i=0; i<10000; i++){
        x = (rand() * rand()) % 1000001;
        printf("%d\n",x);
      }
      return 0;
    }
    

    【讨论】:

    • @Jongware RAND_MAX 保证为 32767 - 所以32767 * 32767 = 1073676289 应该足够了
    • Ta,刚刚注意到您的代码中规避了它的调整。对不起。倍增没有副作用吗?就个人而言,我宁愿使用 XOR 和 shift -- 也许我应该比较这两种方法。
    • @Constantin 通过分解两个 rand() 结果,您不会错过所有高于 RAND_MAX 的素数吗?如果我糟糕的数学技能是正确的,你就不会得到序列中的所有数字。
    • @Constantin:这是对的,但不是你想的那样。使用乘法,没有办法得到 32771。
    • @Jongware 我会开枪并断言“显然答案很差”。调用 rand() 两次就像是 2 个 32768 面骰子和 32768*32768 组合。 1000001改装的产品分布最不均匀。平均出现次数应为 ~1074,但 0 出现 67479 次,而 896370 仅出现 800 次(最差)。
    猜你喜欢
    • 1970-01-01
    • 2014-10-17
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 2014-04-11
    相关资源
    最近更新 更多