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

Искам да направя генератор на произволни числа, където потребителят определя диапазона и количеството на генерираните числа. Искам да направи всяко число уникално (без повторение). Това е, което направих досега (генерира, но някои от тях се повтарят, защо?)

#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
Хм. Мисля, че ако OP използва printf/scanf std::set най-вероятно все още не е покрит..   -  person drescherjm    schedule 04.11.2014
comment
Добре, но можете ли да ми кажете защо кодът ми не работи? Теоретично трябва да го направи.   -  person user3478487    schedule 04.11.2014
comment
@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
да, но OP не иска ефективно решение. - 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-цикъл. Генерирате нов номер за number[i], но нямате гаранция, че този номер е уникален. Можете също така да зададете номер [i] на друг дубликат.

Ако искате вашият код да работи, трябва да продължите да променяте номер[i], докато има дубликат.

Това се отнася до грешката във вашия код. От друга страна, този код е ужасно неефективен, така че трябва да обмислите оптимизирането му, ако планирате да изпълнявате тази процедура често.

person Tomek    schedule 04.11.2014