Προς το περιεχόμενο

Random Number Generator C++


Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα,

 

Αντιμετωπίζω ένα πρόβλημα με την συνάρτηση random(int num) της C++. Γνωρίζω την βασική της λειτουργία, αλλά κάθε φορά που την καλώ βγάζει τους ίδιους αριθμούς. Για παράδειγμα, έχω ένα μονοδιάστατο πίνακα a[10], τον οποίο θέλω να γεμίσω με τυχαίους αριθμούς από το 0 μέχρι το 10, κάθε φορά που τρέχω το πρόγραμμα. Αν χρησιμοποιήσω την random(10) μέσα σ' ένα βρόγχο, ναι μεν τον γεμίζει κανονικά με τυχαίους αριθμούς αλλά κάθε φορά που τρέχω το πρόγραμμμα εμφανίζει ακριβώς τους ίδιους.

Δημοσ.

Μήπως εννοείς τη συνάρτηση: rand() ;

 

Αν ναι, πρέπει πρώτα να καλέσεις (μια φορά) την srand() η οποία αρχικοποιεί τη γεννήτρια ψευδοτυχαίων. Η πιο δημοφιλής αρχικοποίηση είναι με την τρέχουσα ώρα του συστήματος:

 

>

srand( time(0) );
...
int x = rand();

Δημοσ.

τι γεννήτρια παραγωγής τυχαίων αριθμών χρησιμοποιείς;

 

για random συνάρτηση δε γνωρίζω

 

πάντως μπορείς να χρησιμοποιήσεις την rand()

 

αρχικά μέσω της srand θέτεις ως γεννήτρια παραγωγής τυχαίων αριθμών την ώρα του συστήματος και μετά με την rand κάθε φορά που θα τρέχεις το πρόγραμμα θα παράγονται διαφορετικοί αριθμοί

 

πχ

 

>
#include <iostream>
#include <ctime>

int main(void){

srand(time(NULL));
int foo = rand()%10;

std::cout<<foo<<std::endl;
std::cin.get();

return 0;
}

 

edit: με πρόλαβε ο migf1 :P

Δημοσ.

Ευχαριστώ παιδιά, έτσι δούλεψε

 

>
int a[10];
srand( time(0) );
for(int i=0;i<10;i++)
{
       a[i]= 1+random(9);
       cout<<a[i]<<endl;
}

 

Ουσιαστικά τα στοιχεία του πίνακα θα έχουν τιμές από 1 εώς 9

Δημοσ.

Μάλλον θα είναι non-portable extension.

 

Με στάνταρ C/C++ αυτό που θες να κάνεις γίνεται ως εξής:

 

>
...
srand( time(0) );
...
a[i] = 1 + rand() % 9;
...

Δημοσ.

Και δεν τη φτιάχνεις μόνος σου...

 

>
#include <ctime>

int random( int lim )
{
srand( time(0) );
return rand() % lim;
}

int main( void )
{
	...
a[ i ] = 1 + random(9);
...
}

Κάνει και re-initialize τη γεννήτρια, οπότε δεν χρειάζεται να την κάνεις εσύ έξω από τη συνάρτηση ;)

Δημοσ.

Αξίζει να πούμε ότι το γεγονός ότι η rand() βγάζει τα ίδια αποτελέσματα κάθε φορά δεν είναι λάθος.

 

Η rand() παράγει ψευδοτυχαίους αριθμούς, δηλαδή αριθμούς που δεν παρουσιάζουν κάποια κανονικότητα ως ακολουθία και έτσι μοιάζουν να είναι τυχαίοι. Όμως δεν πρόκειται για τίποτα άλλο από μια συγκεκριμένη ακολουθία αριθμών (ασφαλώς όχι αποθηκευμένων αλλά που παράγονται αλγοριθμικά). Αυτό που κάνει η srand() είναι να λέει στην rand() από ποιο σημείο της ακολουθίας να ξεκινήσει να δίνει αριθμούς. Όταν βέβαια καλείται με όρισμα την τρέχουσα ώρα, κάθε φορά που τρέχει το πρόγραμμα η ακολουθία θα ξεκινάει από διαφορετικό σημείο.

 

Το ότι οι αριθμοί μοιάζουν να είναι τυχαίοι αλλά είναι πάντα οι ίδιοι (με ίδιο όρισμα στην srand()) μας δίνει τη δυνατότητα να δοκιμάσουμε το πρόγραμμα. Σκεφτείτε ότι φτιάχνετε ένα πρόγραμμα που χειρίζεται τυχαίους αριθμούς, αλλά έχει ένα σφάλμα. Αν η είσοδος των τυχαίων αριθμών που προκαλεί το σφάλμα μπορεί να επαναληφθεί, τότε υπάρχει κάποια ελπίδα να μπορέσουμε να παρακολουθήσουμε το πρόγραμμα ώστε να βρούμε το σφάλμα! Αν δεν μπορούσαμε να λάβουμε την ίδια είσοδο γιατί οι αριθμοί θα ήταν πραγματικά τυχαίοι κάθε φορά, θα ήταν πιο δύσκολο να συναντήσουμε πάλι το σφάλμα.

 

 

Με βάση τα παραπάνω, καλύτερο θα ήταν η υλοποίηση της random(int) που προτείνεται παραπάνω να μην περιέχει την κλήση στην srand() ώστε να συμπεριφέρεται όσο το δυνατόν πιο κοντά στην απλή rand() -- και μετά αν κάποιος θέλει καλεί την srand() αν και όταν θέλει.

Δημοσ.

...

Με βάση τα παραπάνω, καλύτερο θα ήταν η υλοποίηση της random(int) που προτείνεται παραπάνω να μην περιέχει την κλήση στην srand() ώστε να συμπεριφέρεται όσο το δυνατόν πιο κοντά στην απλή rand() -- και μετά αν κάποιος θέλει καλεί την srand() αν και όταν θέλει.

 

Έτσι όπως τα λες φίλε nplatis είναι (για αυτό και στα αρχικά μας post γράψαμε για ψευδοτυαίους), με μια μικρή επιφύλαξη για το αν πρέπει ή όχι να γίνεται re-seed η γεννήτρια μέσα στην random(). Αν γίνεται μέσα στη συνάρτηση κάθε φορά που καλείται, τότε κάνει το πρόγραμμα λίγο πιο ασφαλές, υπό την έννοια πως δυσκολεύει λίγο περισσότερο τον κακόβουλο να βρει τον ακριβή αριθμό που παράγει κάθε φορά η συνάρτηση. Υπό αυτή την έννοια λοιπόν ίσως είναι καλύτερα να γίνεται re-seed η γεννήτρια μέσα στην random(), και όταν χρειάζεται debugging να χρησιμοποιείται η απλή rand()... ενδεχομένως με χρήση κάποιου pre-processor directive...

 

>
int random( int lim )
{
#if !DEBUG
srand( time(0) );
#endif

return rand() % lim;
}

 

Βέβαια γενικότερα, ασφάλεια & srand() είναι... αντιφατικές έννοιες :lol:

Δημοσ.

Τα πάντα είναι ζήτημα του τι θέλει να κάνει κανείς. Πάντως η φιλοσοφία της C είναι η συνάρτηση να κάνει ένα απλό πράγμα, ενώ αν μπει μέσα και η srand() κάνει δύο πράγματα. Επίσης αν κάποιος γνωρίζει την rand() τότε θα περιμένει και η όποια random(int) να μην καλεί από μόνη της την srand(). Γενικά νομίζω ότι σε μια βιβλιοθήκη δεν θα έβαζες ποτέ random(int) που να περιέχει την κλήση της srand().

Δημοσ.

Σε μια βιβλιοθήκη θα μπορούσες να βάλεις μια 2η παράμετρο, bool, π.χ...

 

>
int random( int lim, bool reseed );

 

EDIT 1:

 

και να παρέχεις κι ένα σχετικό constant directive, π.χ.

 

>
#define RND_RESEED 1

 

ώστε όταν καλείς τη συνάρτηση αντί να περνάς δυσνόητα true ή false να γράφεις π.χ...

 

>
...
random( 100, !RND_RESEED );	/* αντί για random( 100, false ); */
...
random( 2000, RND_RESEED );	/* αντί για: random( 2000, true ); */
...

 

EDIT 2:

 

Και για να είμαστε πλήρως portable (να μη βασιζόμαστε δηλαδή στην implementation dependent διαχείριση του 1 ως true, το directive σε C++ θα πρέπει να το κάνουμε...

 

>
#define RND_RESEED  true

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...