Αρχές Προγραμματισμού (C)
Κατασκευή δομής Bitmap Παραγωγή (ψευδο)τυχαίων αριθμών
Δομή Bitmap /* bits: το bitmap, pos: η θέση του bit που θα θέσουμε τιμή, state: η τιμή */ /* που θα θέσουμε (0 ή 1) */ void bit_set(unsigned char *bits, int pos, int state) { unsigned char mask; int i; /* Set a mask for the bit to set */ mask = 0x80; for (i = 0; i < (pos % 8); i++) mask = mask >> 1; /* Set the bit. */ if (state) bits[pos / 8] = bits[pos / 8] | mask; else bits[pos / 8] = bits[pos / 8] & (~mask); return; }
(Ψευδο)Τυχαίοι αριθμοί Η rand παρέχει έναν μηχανισμό παραγωγής τυχαίων αριθμών. Δεν μας δίνει όμως πάντοτε το διάστημα τιμών μέσα από το οποίο θέλουμε να πάρουμε τυχαίους αριθμούς. Π.χ., θέλουμε να παράγουμε τυχαία δύο μόνο αποτελέσματα που αντιστοιχούν σε ρίψεις κέρματος κορώνα-γράμματα. Πώς μπορούμε να παράγουμε τέτοιες τυχαίες ρίψεις;
(Ψευδο)Τυχαίοι αριθμοί [0 ... RAND_MAX] Διαιρούμε το διάστημα στα 2: [0 ... RAND_MAX/2] [RAND_MAX/2+1 ... RAND_MAX] Όταν η rand() δίνει αριθμό από το αριστερό κομμάτι, τότε είναι σαν να έχουμε ‘κορώνα’. Όταν η rand() δίνει αριθμό από το δεξί κομμάτι, τότε είναι σαν να έχουμε ‘γράμματα’.
#include <stdio.h> #include <stdlib.h> main() { int i; int num; printf("\%s %d", "In this computer, RAND_MAX=", RAND_MAX); printf("\nWe generate 10 random coin trials."); for (i=0; i<10; i++) num = rand(); if ( num <= RAND_MAX/2 ) printf("\n%s", "head"); else printf("\n%s", "tails"); } $ ./a.exe In this computer, RAND_MAX= 2147483647 We generate 10 random coin trials. head tails
(Ψευδο)Τυχαίοι αριθμοί Θέλουμε να παράγουμε τυχαία έξι μόνο αποτελέσματα που αντιστοιχούν σε ρίψεις ζαριού. Πώς μπορούμε να παράγουμε τέτοιες τυχαίες ρίψεις; Πρέπει να ‘μετατρέψουμε’ την ευθεία των αριθμών [0 .......................................................RAND_MAX] στα διακριτά διαστήματα [ 1 | 2 | 3 | 4 | 5 | 6 ]
(Ψευδο)Τυχαίοι αριθμοί Κανονικοποιούμε το αποτέλεσμα της rand(), ώστε να μετατραπεί σε αριθμό κινητής υποδιαστολή d, όπου 0 <= d < 1. d = (double) rand() / ( (double) RAND_MAX + 1) Μετατροπή τύπων (cast) Το διάστημα των πιθανών τιμών της d είναι τώρα: [0 ................................................. 1) Πώς θα επεκτείνουμε το διάστημα για να καλύπτει τιμές της d μέχρι 6; [0 ................................................. 6) d * 6 Πώς θα παίρνουμε μόνο διακριτές τιμές 0, 1, 2, 3, 4, 5, 6 και όχι π.χ. 2.3, 4.5, κ.λ.π.; Ξανά μετατροπή τύπου: (int) d * 6
#include <stdio.h> #include <stdlib.h> main() { int i,k; double d; printf("\%s %d", "In this computer, RAND_MAX=", RAND_MAX); printf("\nWe generate 10 random dice trials."); for (i=0; i<10; i++) d = (double) rand() / ( (double) RAND_MAX + 1); d = d * 6 + 1; k = (int) d; printf("\n%d", k); } $ ./a.exe In this computer, RAND_MAX= 2147483647 We generate 10 random dice trials. 1 5 4 3 2 Χωρίς το ... + 1 οι αριθμοί που επιστρέφονται είναι από 0 ως 5.
(Ψευδο)Τυχαίοι αριθμοί Αν τρέξουμε το πρόγραμμα πολλές φορές θα πάρουμε τα ίδια αποτελέσματα!
(Ψευδο)Τυχαίοι αριθμοί Ο λόγος: η rand() για να δουλέψει πρέπει να αρχικοποιηθεί με κάποιον αριθμό. Ο αριθμός αυτός είναι πάντα ο ίδιος, εκτός και αν ζητήσουμε εμείς οι ίδιοι να αλλάξει. Αν δεν αλλάξει, τότε η rand() σε διαφορετικά τρεξίματα του προγράμματος (σε διάφορες χρονικές στιγμές) θα δώσει την ίδια σειρά (ψευδο)τυχαίων αριθμών. Για να αλλάξει πρέπει να καλέσουμε τη συνάρτηση srand((int) time(NULL)); δίνει αρχική τιμή την τρέχουσα ώρα του συστήματος, ώστε σε κάθε τρέξιμο του προγράμματος να είναι διαφορετικό!
#include <stdio.h> #include <stdlib.h> void initRandom(); main() { int i,k; double d; printf("\%s %d", "In this computer, RAND_MAX=", RAND_MAX); printf("\nWe generate 10 random dice trials."); initRandom(); for (i=0; i<10; i++) d = (double) rand() / ( (double) RAND_MAX + 1); d = d * 6 + 1; k = (int) d; printf("\n%d", k); } void initRandom() { srand((int) time(NULL)); }
(Ψευδο)Τυχαίοι αριθμοί Τώρα, με την κλήση της initRandom(), αν τρέξουμε το πρόγραμμα πολλές φορές θα πάρουμε διαφορετικά αποτελέσματα!