【问题标题】:How can I use the rand() function to generate a different number that hasn't been generated before?如何使用 rand() 函数生成以前未生成的不同数字?
【发布时间】:2023-03-09 15:07:01
【问题描述】:

// 我的意思是通过我的例子来说明:

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

int i;
int a;


for (a = 0;a <10;a ++) {
    i = (rand()%10)+1; // generates a number from 1-10
    printf("%d\n", i);
}

// 我希望循环生成一个数字,该数字给出一个以前没有生成的数字。例如,这样的输出:

1,3,6,2,8,9,4,10,5,7

代替:

3,9,10,3,7,9,2,7,10,1

换句话说,我不想要副本。

【问题讨论】:

标签: c random


【解决方案1】:

您显然不只是希望没有副本,而是希望给定集合中的每个数字都恰好一次。正如罗伯特所说,这类似于洗牌。 C 中没有“甲板”,但可以将其建模为数组:

int deck[] = {1,1,1,1,1,1,1,1,1,1};

这应该代表 10 个不同的“卡片”(由它们在数组中的索引标识),每一张都可用一次。现在,只需编写“绘制”卡片的代码:

int i = 0;  // starting point for searching for the next card to draw
for (int n = 10; n > 0; --n)  // how many cards are left
{
    int skip = rand() % n;  // randomly skip 0 .. n cards
    while (1)
    {
        if (deck[i])             // card still available?
        {
            if (!skip) break;    // none more to skip -> done
            --skip;              // else one less to skip
        }

        if (++i > 9) i = 0;      // advance index, wrapping around to 0
    }
    deck[i] = 0;              // draw the card
    printf("%d\n", i+1);      // and print it out
}

当然,首先播种 PRNG(例如 srand(time(0))),这样您就不会每次都得到相同的序列。

【讨论】:

    【解决方案2】:

    问题中显示的想法是打印一个范围内的数字,不重复。这是一种方法,将每个值放入一个数组并交换其元素。

    一种变化可能是您不想使用所有可能的数字,在这种情况下只需更改PICKED

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define ARRLEN 10
    #define PICKED 10
    
    int main(void) { 
        int array[ARRLEN];
    
        srand((unsigned)time(NULL));        // seed the PRNG
    
        for(int i = 0; i < ARRLEN; i++) {       // generate the numbers
            array[i] = i + 1;
        }
    
        for(int i = 0; i < ARRLEN; i++) {       // shuffle the array
            int index = rand() % ARRLEN;
            int temp = array[i];
            array[i] = array[index];        // by randomly swapping
            array[index] = temp;
        }
    
        for(int i = 0; i < PICKED; i++) {       // output the numbers
            printf("%d ",  array[i]);
        }
        printf("\n");
    }
    

    程序输出:

    9 8 4 5 1 10 7 3 6 2

    图书馆的 PRNG 不是很随机,但在很多情况下这并不重要。如果是,则可以使用更好的算法。

    【讨论】:

    • 此代码可以适应The Danger of Naiveté 中显示的场景,其中 ARRLEN 和 PICKED 都设置为 3。然后可以重复运行或进一步修改以将main() 中的大部分内容提取到一个可以从main() 多次调用的函数shuffle_once() — 当然,将srand() 留在修改后的main() 中。当运行 60000 次迭代,然后通过 sort | uniq -c | sort -n 运行时,您会得到倾斜的输出,例如:8754 3218869 3128966 12311005 23111126 13211280 213
    猜你喜欢
    • 2015-09-29
    • 2011-05-15
    • 2020-06-26
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多