Мой собственный генератор случайных чисел

Я хочу создать генератор случайных чисел, в котором пользователь указывает диапазон и количество сгенерированных чисел. Я хочу, чтобы каждый номер был уникальным (без повторения). Это то, что я сделал до сих пор (он генерирует, но некоторые из них повторяются, почему?)

#include <time.h>
#include <stdio.h>
#include <windows.h>
#include <conio.h>

int main()
{
    srand(time(NULL));

    int start, stop, amount;

    system("chcp 1250 >nul");

    printf("Welcome to random number generator!\n");
    printf("\nWhat range? \nFrom: "); scanf("%i", &start);
    printf("To: "); scanf("%i", &stop);

    printf("\nHow many numbers?: "); scanf("%i", &amount);
    int number[amount];

    for(int i=0; i<amount; i++)
    {
        number[i] = rand() % ((stop+1)-start) + start;

            for(int j=i; j>-1; j--)
            {
                if(number[i]==number[j])
                {
                    number[i] = rand() % ((stop+1)-start) + start;
                }
            }

        printf("\n%i generated number: %i", i+1, number[i]);
        Sleep(10);
    }

    getch();
}

person user3478487    schedule 04.11.2014    source источник
comment
Используйте std::set, вставляйте в набор, пока в нем не будет amount чисел. Также используйте <random> вместо rand()   -  person Borgleader    schedule 04.11.2014
comment
Хм. Я думаю, что если ОП использует printf/scanf std::set, скорее всего, это еще не было рассмотрено.   -  person drescherjm    schedule 04.11.2014
comment
Хорошо, но не могли бы вы сказать мне, почему мой код не работает? Теоретически он должен это сделать.   -  person user3478487    schedule 04.11.2014
comment
@user3478487 user3478487 Вы не проверяете, не является ли второе задание дубликатом. Если вы создаете новый номер, вам необходимо сбросить j на i-1 после переназначения number[i]. Кроме того, в нынешнем виде вы всегда выполняете одно повторное назначение, поскольку вы сравниваете number[i] == number[j], когда i и j равны, j следует инициализировать до i-1.   -  person IllusiveBrian    schedule 04.11.2014
comment
Что, если число больше, чем интервал (отредактируйте: извините, также упомянуто Марком Б.)? Также обратите внимание, что вы полагаетесь на расширение компилятора, когда делаете int number[amount].   -  person JorenHeit    schedule 04.11.2014


Ответы (2)


Ваш цикл "проверить наличие дубликатов" неверен. Вы можете найти дубликат, но тогда вы не проверяете, существует ли этот повторно сгенерированный номер в материале, который вы УЖЕ протестировали.

например рассмотрим такой массив. пользователь запросил 5 номеров, диапазон 1-10

number[0] = 5
number[1] = 6
number[2] = 2
number[3] = 8

Теперь вы работаете над номером [4]. Вы генерируете 2... Вы сканируете массив в обратном направлении и обнаруживаете, что 2 — обман. Итак, вы создаете новый номер... и генерируете 8. Но вы не сбрасываете свой цикл j — вы просто продолжаете работать в обратном направлении и никогда не видите, что 8 уже был в массиве.

У вас должно получиться что-то вроде:

        for(int j=i; j>-1; j--) {
            if(number[i]==number[j]) {
                number[i] = rand() % ((stop+1)-start) + start;
                j = i; // RESET THE LOOP
            }
        }

И обратите внимание, что ваш код может легко создать бесконечный цикл. например представьте, что кто-то запрашивает числа в диапазоне 1-3, и сгенерируйте 4 из них. 1,2,3,?. Условие никогда не может быть выполнено, потому что у вас не может быть 1-3 без хотя бы одного повторения.

person Marc B    schedule 04.11.2014
comment
это очень неоптимальное решение. Это сработает, но представьте, что произойдет, если вы пытаетесь сгенерировать много чисел и близки к концу. вы создаете обман большую часть времени и продолжаете повторять этот цикл. - person Tomek; 04.11.2014
comment
да, но ОП не просит эффективного решения. - person Marc B; 04.11.2014
comment
Я просто хочу, чтобы он знал об этом. Это может быть проблемой, особенно с реальными генераторами случайных чисел, которые на самом деле не являются однородными. Он будет использовать все частые значения в самом начале, а затем может застрять, пытаясь найти оставшиеся числа. - person Tomek; 04.11.2014
comment
вам нужно изменить j = i на j = i - 1 или этот цикл никогда не закончится. - person Tomek; 06.11.2014

Таким образом, даже если мы предположим, что rand() — идеальный генератор случайных чисел, числа будут повторяться. Допустим, вам нужно сгенерировать 100 номеров. Скажите, что ваш старт = 1 и стоп = 100.

вы создаете первое число от 1 до 100, затем второе и так далее. Чем больше чисел вы уже использовали, тем легче получить дубликат.

Затем вы найдете дубликат с этим внутренним циклом for. Вы создаете новый номер для номера [i], но у вас нет гарантии, что этот номер уникален. Вы также можете установить number[i] для другого дубликата.

Если вы хотите, чтобы ваш код работал, вы должны постоянно менять номер [i], пока у него есть дубликат.

Это что касается ошибки в вашем коде. С другой стороны, этот код ужасно неэффективен, поэтому вам следует подумать об его оптимизации, если вы планируете часто запускать эту процедуру.

person Tomek    schedule 04.11.2014