Rand ja for-looppi (apua koodiin)

Viestiketju alueella 'Ohjelmointi' , aloittaja Bou5, 29.09.2019.

NOSTOJA MUROPAKETIN SISÄLLÖSTÄ
  1. Bou5

    Rekisteröitynyt:
    29.09.2019
    Viestejä:
    2
    Moi,

    Pitäisi siis tehdä ohjelma, joka antaa satunnaislukuja niin monta kierrosta, kun käyttäjä haluaa. Ongelma on nyt se, että antaa samat random luvut kaikilla kierroksilla. Missä tässä on virhe?

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

    using namespace std;

    int main()
    {

    char uusi = 'k';

    while (uusi == 'k')
    {
    int n;
    cout << "Monta kertaa arvotaan? \n";
    cin >> n;
    cout << endl << endl;

    for ( int a = 1; a <= n; a++)
    {

    int random_1 = 0, random_2 = 0;

    srand(time(NULL)); // satunnaisluvun ns. siemenluku haetaan kellosta

    random_1 = 0 + rand() % 11; // satunnaisluku 0-10
    random_2 = 50 + rand() % 51; // satunnaisluku 50-100

    cout << a << ". kierros: \n"; // tulostaa monesko kierros on menossa
    cout << "Satunnaisluvuksi valilta 0-10 tuli " << random_1 << endl;
    cout << "Satunnaisluvuksi valilta 50-100 tuli " << random_2 << endl << endl;

    } // FOR-loopin loppu

    cout << endl << "Uudelleen? (k/e)" << endl;
    cin >> uusi;
    cout << endl;

    } // While-loopin loppu

    cout << "Ohjelma on loppu" << endl << endl;
    system("pause");
    return 0;
    }
     
  2. Paapaa

    Rekisteröitynyt:
    14.04.2005
    Viestejä:
    11 048
    Kun alustat siemen, arvotaan sen jälkeen aina samat luvut tuolle siemenelle. Alusta se siis vain kerran, älä joka kierroksella.
     
    Bou5 tykkää tästä.
  3. Bou5

    Rekisteröitynyt:
    29.09.2019
    Viestejä:
    2

    Siinä se virhe oli. Kiitos
     
    Paapaa tykkää tästä.
  4. Tronic

    Rekisteröitynyt:
    21.06.1999
    Viestejä:
    1 718
    Tuollainen kellosta alustaminen ottaa ajan vain sekunnin tarkkuudella. Koska looppisi jokainen kierros ajetaan sen saman sekunnin aikana, saat myös samat luvut. Vaikka siirsit alustuksen loopin ulkopuolelle, tuottaa ohjelmasi samat luvut, kun se ajetaan saman sekunnin aikana useaan kertaan.

    C++:ssa kannattaa käyttää tässä käytetyn C-kielen rand-funktion sijaan C++:n randomia, joka toimii nopeammin, osaa antaa lukuja suoraan halutulta väliltä ja joka voidaan kellonajan sijaan alustaa oikealla randomilla. Haittapuolena on muutama rivi ylimääräistä koodia ohjelman alkuun.

    Koodi:
    #include <iostream>
    #include <random>
    
    int main() {
        std::mt19937_64 random_gen;
        std::uniform_int_distribution dice(1, 6);
        for (unsigned i = 0; i < 5; ++i)
            std::cout << dice(random_gen) << std::endl;
    }
    
    Ideana on luoda yksi random-generaattori, jota sitten käytetään satunnaislukujen tuottamiseen halutun distribuution mukaisesti. Tässä luodaan nopan silmälukuja yhdestä kuuteen (uniform tarkoittaa että jokainen luku on yhtä todennäköinen). Kryptisesti nimetty mt19937_64 on nopein standardikirjaston generaattoreista.

    Yllä oleva ohjelma kuitenkin tuottaa joka ajokerralla saman sarjan lukuja, joten lisätään vielä seeding käyttöjärjestelmän tarjoamasta randomista std::random_device avulla:

    Koodi:
    #include <array>
    #include <iostream>
    #include <random>
    
    /// Construct a fast random number generator seeded with true random
    template<typename Gen=std::mt19937_64> Gen random_generator() {
        std::random_device rd;  // Slow but true random numbers
        std::array<int, Gen::state_size> seed;
        for (int& val: seed) val = rd();
        std::seed_seq seed_seq(begin(seed), end(seed));
        return Gen(seed_seq);
    }
    
    int main() {
        auto rg = random_generator();
        std::uniform_int_distribution dice(1, 6);
        std::bernoulli_distribution unfair_coin(0.8);  // 80 % heads
        for (unsigned i = 0; i < 5; ++i)
            std::cout << dice(rg) << std::endl;
        for (unsigned i = 0; i < 5; ++i)
            std::cout << (unfair_coin(rg) ? "Heads" : "Tails") << std::endl;
    
    }
    
    Nyt ohjelma tuottaa joka ajokerralla erilaisia sarjoja. Lisäksi laitoin esimerkin vuoksi myös toisen distribuution, joka käyttää samaa generaattoria erilaisten satunnaislukujen tuottamiseen. Generaattoria voi käyttää myös std::random_shuffle-funktion kanssa esim. korttipakan sekoittamiseen.
     
    Viimeksi muokattu: 06.10.2019
Tagit:

Jaa tämä sivu

Alibi
Anna
Deko
Dome
Erä
Hymy
Kaksplus
Kippari
Kotilääkäri
Kotiliesi
Koululainen
Ruoka.fi
Parnasso
Seura
Suomen Kuvalehti
TM Rakennusmaailma
Tekniikan Maailma
Vauhdin Maailma
Golfpiste
Vene
Nettiauto
Ampparit
Plaza
Muropaketti