数字的随机数组不会通过整数范围吗?

时间:2018-11-16 18:16:41

标签: c++ arrays random

long long x[1000000], n, small, big;
    main(){
        cin >> n; //range
        cin >> small; cin >> big;
        srand(time(NULL));
        for (int i=0; i<n; i++){
            x[i]=small + rand()%(big-small+1);
        }
        merge_sort(x,0,n-1);
        for (int i=0; i<n; i++){
            cout << x[i] << " ";
        }
    }

(忽略merge_sort,我只用它来查看最高的数字)

所以我确保所有变量都在 long long 中,但是所有随机x [i]都不会通过整数范围(32768)。有人知道为什么吗?

some example

1 个答案:

答案 0 :(得分:1)

与所有随机数生成器一样,std::rand()会生成有限范围内的数字。所有值均大于或等于0,并且所有值均小于或等于RAND_MAXRAND_MAX的值取决于您使用的实现。您可以查看它以查看上限:

std::cout << RAND_MAX << '\n';

有些技术可以根据随机数生成器的结果创建更大或更小的范围。使用较新的<random>类,您将使用std::uniform_int处理细节。使用std::rand(),您必须滚动自己的代码。

要缩小范围,大多数人的本能是使用其余的部分,就像问题中的代码一样。可以,但是可能会导致失真。举一个极端的例子,假设RAND_MAX是32767,并且您想生成[0 .. 32766]范围内的值。因此,您使用rand() % 32767,它将为您提供该范围内的值。 但是存在一个问题:每当rand()产生0时,您将得到0;当它产生1时,您将得到1,依此类推,直到32766。但是当rand()产生32767,您得到0。也就是说,rand()产生0 时得到0,产生32767,但是您只从{{ 1}}。如果rand()完全统一(没有RNG),则您获得0的频率是获得其他任何值的两倍。当您要生成的范围比RNG生成的总范围小得多时,这种失真就不会那么大,并且可以接受。

要正确执行此操作,必须丢弃值。丢弃值的最简单方法是忽略大于所需值的值:

rand()

但是如果int res = rand(); while (res > my_max_value) res = rand(); 很小,这将丢弃很多值,浪费大量时间。因此,更好的方法是将丢弃与余下的部分结合起来:

my_max_value

我没有正确地进行计算;例如,如果int max = ((RAND_MAX + 1) / my_max_value) * my_max_value; int res = rand(); while (res >= max) res = rand(); res %= my_max_value; 等于RAND_MAX,则加1将溢出。剩下的修正工作供读者练习。

INT_MAX将是max的最大倍数,小于或等于my_max_value。该代码将丢弃大于或等于该值的值,并在找到合适的值时将剩余的值保留。

要创建一个大于RNG范围的范围,请“平铺”多个值。例如,如果RAND_MAX是32767,并且您需要RAND_MAX范围内的值(上限是(32767 << 15)+ 32767),则您将两次调用[0 .. 1073741823],将其移位1剩下15个结果,然后加上另一个结果。如果您没有这么方便的值,则必须通过平铺创建一个大于目标范围的范围,然后像我之前讨论的那样减小结果范围。

请注意,无论您使用哪种RNG,都必须完成所有操作。当所有这些计算都封装在rand()中时,在C ++ 11中更加方便,这是使用C ++ 11 RNG和发行版的一个很好的理由。