【问题标题】:ANSI C / rand() % 7 first value is always 3 [duplicate]ANSI C / rand() % 7 第一个值始终为 3 [重复]
【发布时间】:2014-06-27 17:57:56
【问题描述】:

所以想弄清楚 C 中 rand() mod k7 有什么特别之处。在另一篇文章中,有人说 C rand() 使用 http://en.wikipedia.org/wiki/Linear_congruential_generator,但我看不出是什么使 (mod k7) k-> 标量专用于与 ANSI C 相关的算法。

所以我有以下代码:

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

void getRand(int* num1, int* num2, int* num3);


int main(int argc, const char * argv[])
{
    int i = 0;
    for (i = 0; i < 100; i++) {

        srand(time(NULL));
        printf("%d\n", rand() % 7 );

        sleep(1);
    }
    return 0;
}

这总是打印 3。但如果我使用任何 n 使得 7 不除 n,我会得到更好的第一个值序列。显然仍然不是随机的,但比 3 或一些 c mod 7 = 3 更好。

我特意在循环中使用种子以这种方式编写程序,以表明第一个值始终返回 3,而不管种子如何。

是的,我可以得到 Xn n &gt; 0 的随机数,但我希望每个 Xo 都有 X1 % 7 != X1 % 7

【问题讨论】:

  • 你应该只调用一次srand()
  • 即使使用reseed,它仍然会打印出一堆3。我希望 rand() 开始值每秒都在变化,因为 time() 每秒都在变化,但似乎没有。 srand() 显然不是那么精细。
  • @RobertHarvey 他正在通过time() 更改种子并休眠。它们之间的关系完全不明显。我最初的经历是 100 次迭代都将在一秒钟内完成,所以 time() 都将返回相同的数字。
  • 我使用 gcc 4.8.2 得到以下输出序列:6 1 3 6 3 5 1 5 0 2。我将循环更改为仅计算 10 次。
  • 我读了这个,然后是元数据,然后是这个,然后是元数据,然后 THEN 我理解了这个问题。我认为。问题是为什么 rand()%7 总是返回 3 ,即使种子有 100 个唯一时间。这个问题非常不清楚。特别是因为有几个我不熟悉的缩写和符号:“`如果我使用任何 n s.t. !(7|n),`”

标签: c random modulus srand


【解决方案1】:

好的,让我们从不仅仅是几个数据点开始:

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


int main(int argc, const char * argv[])
{
    size_t counters[7] = {0,0,0,0,0,0,0};
    time_t tt = time(NULL);

    //for (size_t i = 0; i < 7; i++) {
    //  printf("result: %d count: %d\n", i, counters[i]);
    //}

    for (size_t i = 0; i < 1000000; i++) {
        srand(tt + i);
        counters[rand() % 7] ++;
    }

    for (size_t i = 0; i < 7; i++) {
        printf("result: %d count: %d\n", i, counters[i]);
    }
}

有了这个,在 Windows 7 上,Visual Studio 2013 编译为 C++

result: 0 count: 142894
result: 1 count: 142850
result: 2 count: 142848
result: 3 count: 142855
result: 4 count: 142854
result: 5 count: 142845
result: 6 count: 142854

你会得到什么,因为我怀疑你会从更大的数据集中得到更好的结果。

【讨论】:

  • 当然,您真正展示的是这不会影响 Visual C++ 的运行时库。 (基于在问题中使用unistd.h,我几乎可以肯定它没有在 Windows 上测试)
  • @BenVoigt 是的,我也明白了……但我的两个问题是“所以你 %7 兰特,播种后得到 3 兰特,那又怎样?”和“当你测试更大的数据集时会发生什么”所以这是我的更大的数据集代码供 OP 测试。
  • @SimeonPilgrim 首先感谢您尝试为我解决这个问题。这是我的输出:代码结果:0 计数:127773 结果:1 计数:127773 结果:2 计数:172736 结果:3 计数:188398 结果:4 计数:127774 结果:5 计数:127773 结果:6 计数:127773跨度>
  • @thomas。是和不是。这是随机性的近似值,正如 Mooing Duck 指出的那样,使用的模数是否有一个 7 作为最后一个数字,这可以解释很多。那么这有什么关系呢?以及你为什么挂断 %7 兰特的结果。你到底想在这里做什么,这会产生影响。还是您几乎要指出兰特不是加密货币安全的?
  • @SimeonPilgrim:或者使用不同的引擎,arc4random 似乎是其他 XCoders 推荐的解决方法。我不确定在后续结果获得 4 位熵之前必须丢弃多少结果。它甚至有可能永远不会发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多