【问题标题】:How to get a larger random number from the c function rand()如何从 c 函数 rand() 中获取更大的随机数
【发布时间】:2013-04-26 23:19:46
【问题描述】:

我在一个编码环境中,我只能访问一些最基本的 c 函数。 #include'ing other lib 是不可行的。

在这种环境中,我可以调用 rand(),它在我的环境中给我一个介于 0 到 32767 之间的随机数(我认为)。下面的代码是否是正确的逻辑来获得一个像 rand() 一样均匀分布的更大的随机数?

rnum = rand() * (32767 + 1) + rand();

【问题讨论】:

  • 与 rand 一样均匀分布.. 确实是一个很高的赞誉。你真的不能包含 30 行 BSD 许可代码并包含 arc4random 或其他东西来正确完成工作,或者读取 /dev/random 吗?
  • 你应该说出你的环境是什么,但这听起来很垃圾。请告诉我们,您并没有强烈要求这些数字不可猜测!
  • 很多嵌入式环境都受限于哪些库可以立即可用。
  • 我的环境是 HP LoadRunner。仅当 LoadRunner 使用我的代码(LR 脚本)运行负载测试时,才会编译代码。该脚本可以在任何机器上运行,我不能依赖任何已经有一些 lib 文件可以链接的机器。所有代码都用于负载测试测试系统。

标签: c random


【解决方案1】:

rnum = (rand() << 15) | rand() 可能更快,但如果您需要高质量的随机数,您应该寻找外部库。内置随机函数通常仅适用于最简单的应用程序。

【讨论】:

  • 我自己会选择^ 而不是|,以避免在移植到RAND_MAX 值更合理的平台时出现问题。
  • 我将支持Mersenne Twister 的推荐。我自己的OneJoker 库也有一个很好的生成器。
  • 没有理由认为这会比 OP 的解决方案更快,实际上您的解决方案是错误的,因为
  • 你说得对,我有点跑题了。我假设现有的 rand() 是 16 位,而不是 15 位。我将进行编辑。你也是对的,大多数编译器无论如何都会将乘法优化为常数,但仍有一些愚蠢的编译器不会。
  • @LeeDanielCrocker,最愚蠢的编译器是嵌入式编译器。
【解决方案2】:
static unsigned long next = 1;
int my_rand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % (RAND_MAX+1));
}

void my_srand(unsigned int seed) {
    next = seed;
}

在 Linux 上

#define RAND_MAX    2147483647

您的环境 RAND_MAX 可能是 32767

参考:http://en.wikipedia.org/wiki/Linear_congruential_generator

如果您没有内存限制,您还可以查看 http://en.wikipedia.org/wiki/Mersenne_twister 代码是可嵌入的,就像上面的示例一样

【讨论】:

    【解决方案3】:

    在将任何随机数生成器用于重要用途之前,应该对其进行广泛的测试。 Here 是关于此主题的一篇文章的链接。

    关于真实随机数的弱点的有趣背景可以在二战布​​莱切利公园的密码破解者的各种历史中找到。在战争的大部分时间里,德国人和希特勒都认为他们的密码是牢不可破的,因为他们用随机数加密,而英国人在几个月内就完全破解了所有这些密码,因为德国人在实施“随机性”方面存在各种弱点。许多代码在几天或几个月内被充分“扭曲”,即使没有彻底破坏,即使没有完全破坏,也足以使用。

    【讨论】:

      【解决方案4】:

      除了这里提出的其他优秀解决方案之外,您还可以在 RAND_MAX 中进行幂扩展,在用户定义的 MY_RAND_MAX 处截断,并丢弃会导致一致性被破坏的解决方案。

      int myrand(int MY_RAND_MAX)
      {
          int j = 0, num = 0;
      
          // Generate digits for expansion in powers of RAND_MAX, up to acceptable range.
          while (pow(RAND_MAX + 1, j) <= MY_RAND_MAX){
              num = num + rand() * (int)pow(RAND_MAX + 1, j);
              j++; 
          } 
      
          //compute remainder to determine truncation 
          int remainder = ((int)pow(RAND_MAX + 1, j)) % (MY_RAND_MAX + 1); 
      
          // If number is within accepted bounds, mod and return
          if (num <= (  (int)pow(RAND_MAX + 1, j) - remainder ) ){
              return (num % (MY_RAND_MAX + 1)); 
      
          // Else, if number generated exceeds allowed bounds, rerun method.
          }else if (num > (  (int)pow(RAND_MAX + 1, j) - remainder ) ){
              return myrand(MY_RAND_MAX);
      
          }else{
              exit(-1);
          }
      }
      

      您可以凭经验检查此方法是否在给定范围内为您提供了统计上一致的输出。

      我已经对具有不同范围的几次试验进行了此操作,每个试验的样本量为 100000,并且在样本方差和至少 3 sig 的预期方差之间得到了一致。无花果。

      附言我不是编码员,而是最近学习编码的数学家/物理学家,因此我们将不胜感激任何关于我的代码质量的反馈。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-22
        • 1970-01-01
        • 2020-01-20
        • 2020-12-08
        相关资源
        最近更新 更多