View Full Version : [C++] Problema con pseudo numeri random
giovanniverdelegno
09-01-2011, 19:02
Salve a tutti, sono nuovo, e il mio nickname non è il mio nome, ma la semplice traslitterazione (nonché traduzione molto villana) di "Jonny Greenwood" (chitarrista dei Radiohead). Ma non sono qui per parlare di questo, o di me.
Entriamo subito nel problema, sto facendo un programma in C++, il cui fine è quello di simulare i giochi di archimede (quelli che si svolgono ogni anno nel triennio delle scuole superiori). Difatti noi diamo di base le risposte esatte, e facciamo tirare a caso n giocatori (il cui numero sceglieremo noi ovviamente); se le risposte a caso dovessero combaciare con le risposte esatte date come costanti, alla somma finale si aggiungono 5 punti, se sbagliate, 0. Il problema però non sorge in questa parte, tutto funziona, ma sorge nella creazione dei numeri casuali, vi riporto il codice sorgente del programma con l'errore che ipotizzo (ripreso citando wingman87 in un post simile) sia la fonte dei tanti problemi.
#include <iostream>
#include <ctime>
#include <cmath>
using namespace std;
int main(){
// La sigla "rg" sta per "Risposta Giusta". "rc" per "Risposta a Caso"
int sommarc;
int ferma;
int rg1 = 1;
int rg2 = 3;
int rg3 = 4;
int rg4 = 5;
int rg5 = 2;
//Dichiaro tutti i risultati a caso
int sommarc1,sommarc2,sommarc3,sommarc4,sommarc5;
int n;
cout << "Inserisci il numero dei giocatori ";
cin >> n;
int r1;
int r2;
int r3;
int r4;
int r5;
//time ha una certa precisione, mettiamo che cambia ogni millisecondo:
//siccome molto probabilmente il ciclo for che hai scritto impiega un tempo
//inferiore al millisecondo per essere eseguito ogni volta srand viene
//richiamato con lo stesso parametro, quindi la sequenza di numeri pseudocasuali
//generati da rand riparte sempre dall'inizio
//(cioè si ottiene sempre lo stesso numero).
for(int i=0; i<n; i++){
srand((unsigned)time(0));
r1 = (rand()%5)+1;
cout << r1 << endl;
int rc1 = {r1};
if (rc1 == rg1){
sommarc1 = 5;
}
else{
sommarc1 = 0;
}
cout << "rc1 ";cout << sommarc1 << endl;
}
for(int i=0; i<n; i++){
srand((unsigned)time(0));
r2 = (rand()%5)+1;
cout << r2 << endl;
int rc2 = {r2};
if (rc2 == rg2){
sommarc2 = 5;
}
else{
sommarc2 = 0;
}
cout << "rc2 ";cout << sommarc2 << endl;
}
for(int i=0; i<n; i++){
srand((unsigned)time(0));
r3 = (rand()%5)+1;
cout << r3 << endl;
int rc3 = {r3};
if (rc3 == rg3){
sommarc3 = 5;
}
else{
sommarc3 = 0;
}
cout << "rc3 ";cout << sommarc3 << endl;
}
for(int i=0; i<n; i++){
srand((unsigned)time(0));
r4 = (rand()%5)+1;
cout << r4 << endl;
int rc4 = {r4};
if (rc4 == rg4){
sommarc4 = 5;
}
else{
sommarc4 = 0;
}
cout << "rc4 ";cout << sommarc4 << endl;
}
for(int i=0; i<n; i++){
srand((unsigned)time(0));
r5 = (rand()%5)+1;
cout << r5 << endl;
int rc5 = {r5};
if (rc5 == rg5){
sommarc5 = 5;
}
else{
sommarc5 = 0;
}
cout << "rc5 "; cout << sommarc5 << endl;
}
//La parentesi qua sotto chiude il "for"
//}
//Ora calcolerò la somma totale delle risposte a caso.
sommarc = (sommarc1+sommarc2+sommarc3+sommarc4+sommarc5)/n;
cout << "Il punteggio medio di n giocatori risulta: "; cout << sommarc << endl;
cin >> ferma;
return 0;
}
Quindi, vi chiedo: come fare a dare un seme sempre diverso? Mannaj'al computer, è troppo veloce a fare i calcoli... (magari lo fossi anche io). (no questa è una battuta squallida, non dovrebbe far ridere).
Grazie dell'attenzione!
lo inizializzi una volta fuori dal ciclo e poi usi rand per generare il seed nel for? :E
Supdario
09-01-2011, 19:52
Nel tuo programma ci sono 2 errori concettuali:
1) Usi un ciclo for per inizializzare il generatore pseudorandom: il time() ha una precisione di 1 secondo (quindi cambia di secondo in secondo, e non millisecondo).
2) Il generatore pseudorandom dev'essere inizializzato una volta sola in tutto il programma (all'inizio), non ogni volta che esegui la funzione rand(). :asd:
infatti non capisco la necessità di cambiare il seed, ma se proprio vuoi farlo puoi fare come ho detto
Supdario
09-01-2011, 19:56
infatti non capisco la necessità di cambiare il seed, ma se proprio vuoi farlo puoi fare come ho detto
E' inutile, perché tanto il seed rimane sempre lo stesso (il programma viene eseguito in modo velocissimo, invece il seed cambia solo di secondo in secondo).
giovanniverdelegno
09-01-2011, 20:03
Vi ringrazio per la velocità con cui mi avete risposto e l'interesse mostratomi. (fdskajfadsnfkja)
Allora, ho fatto così perché mettendo il generatore pseudorandom all'inizio, e richiamandolo poi, veniva sempre lo stesso numero. Allora ho provato a inserirlo in ogni for, so che ha poco senso, ma pensavo che in questo modo il programma impiegasse più tempo per fare i calcoli e magari dare un numero diverso, ma è sempre lo stesso numero.
int random_integer;
//Genera 1 numero casuale compreso nell'intervallo 1-5
srand((unsigned)time(0));
random_integer = (rand()%5)+1;
cout << random_integer << endl;
for(int i=0; i<n; i++){
int rc1 = {random_integer};
if (rc1 == rg1){
sommarc1 = 5;
}
else{
sommarc1 = 0;
}
int rc2 = {random_integer};
if (rc2 == rg2){
sommarc2 = 5;
}
else{
sommarc2 = 0;
}
int rc3 = {random_integer};
if (rc3 == rg3){
sommarc3 = 5;
}
else{
sommarc3 = 0;
}
int rc4 = {random_integer};
if (rc4 == rg4){
sommarc4 = 5;
}
else{
sommarc4 = 0;
}
int rc5 = {random_integer};
if (rc5 == rg5){
sommarc5 = 5;
}
else{
sommarc5 = 0;
}
Inizialmente l'avevo ipotizzato così, ma ho provato a cambiarlo in quel modo e niente, il numero pseudorandom è uguale per tutti. Non capisco come fare..
Supdario
09-01-2011, 20:06
Vi ringrazio per la velocità con cui mi avete risposto e l'interesse mostratomi. (fdskajfadsnfkja)
Allora, ho fatto così perché mettendo il generatore pseudorandom all'inizio, e richiamandolo poi, veniva sempre lo stesso numero. Allora ho provato a inserirlo in ogni for, so che ha poco senso, ma pensavo che in questo modo il programma impiegasse più tempo per fare i calcoli e magari dare un numero diverso, ma è sempre lo stesso numero.
Inizialmente l'avevo ipotizzato così, ma ho provato a cambiarlo in quel modo e niente, il numero pseudorandom è uguale per tutti. Non capisco come fare..
Non va bene come pensi di fare.... Il generatore pseudorandom va inizializzato una volta sola, e all'inizio del programma (con srand). Successivamente, vedrai che richiamando la funzione rand() ti verranno fuori tutti numeri diversi e random.
giovanniverdelegno
09-01-2011, 20:25
Ok, quindi non devo fare altro che scrivere questo all'inizio del corpo?
srand((unsigned)time(0));
random_integer = (rand()%5)+1;
e poi richiamare random_integer ?
no wait, se random_integer è una variabile, l'espressione viene valutata una volta, al momento dell'assegnamento, dopo di che se non cambi tu il valore (facendo un altro assegnamento del tipo random_integer = (rand()%5)+1) quel valore non cambia
per fare quella cosa dovresti scrivere una funzione random_integer() del tipo
int random_integer(void)
{
return (rand()%5)+1;
}
oppure una macro, tipo
#define RANDOM_INTEGER() (rand()%5)+1
così ogni volta puoi scrivere RANDOM_INTEGER() e quello viene sostuito con (rand()%5)+1 e, quindi, valutato
giovanniverdelegno
09-01-2011, 20:52
(scusate i miei eventuali errori concettuali, ma è da poco che sono entrato nel mondo del linguaggio di programmazione, e ho delle lacune a cui dovrò porre rimedio prima o poi!)
Ok, allora l'ho scritto così. Però sorge un altro problema. Quello che non ho detto è che alla fine del programma, dove aver fatto tirare n giocatori a nostra scelta, dobbiamo confrontare ogni risposta di ogni giocatore con quelle date (che sono 25 e non 5, qui riporto il programma versione estesa..) e poi calcolare il risultato di ogni giocatore per poi fare media e deviazione standard del risultato finale.
Qui in questa "versione" ciò non potrà mai essere espresso, poichè ho messo un sommarc1,2,3.. ecc, 25, che prenderà non so che cosa (alla fine facendo la media viene un risultato molto grande, 6 cifre!) e è sbagliato.
Come potrei fare per dichiarare un vettore, o qualcosa del genere, che possa raccogliere in esso tutte le risposte 1, tutte le risposte 2, tutte le risposte 3 ecc ecc e poi sommarle alla fine? Del tipo, in ogni "for" dichiarare
vettore[n] = ...
la mia idea era questa, ma non so da dove partire per formalizzarla.
Continuo a ribadire di esservi immensamente grato.
#include <iostream>
#include <ctime>
#include <cmath>
using namespace std;
int main(){
// La sigla "rg" sta per "Risposta Giusta". "rc" per "Risposta a Caso"
int sommarc;
int random_integer;
srand((unsigned)time(0));
#define random_integer() (rand()%5)+1)
//è così che devo dichiararla? oppure metterla ad ognuno?
int ferma;
int rg1 = 1;
int rg2 = 3;
int rg3 = 4;
int rg4 = 5;
int rg5 = 2;
int rg6 = 2;
int rg7 = 1;
int rg8 = 2;
int rg9 = 4;
int rg10 = 5;
int rg11 = 3;
int rg12 = 2;
int rg13 = 1;
int rg14 = 4;
int rg15 = 5;
int rg16 = 3;
int rg17 = 3;
int rg18 = 3;
int rg19 = 2;
int rg20 = 2;
int rg21 = 1;
int rg22 = 3;
int rg23 = 4;
int rg24 = 2;
int rg25 = 5;
//Dichiaro tutti i risultati a caso
int tutte le sommarc che non scrivo altrimenti slargherebbe la pagina, ovvero sommarc1,sommarc2... fino a sommarc25;
int n;
cout << "Inserisci il numero dei giocatori ";
cin >> n;
for(int i=0; i<n; i++){
int rc1 = {random_integer};
if (rc1 == rg1){
sommarc1 = 5;
}
else{
sommarc1 = 0;
}
}
for(int i=0; i<n; i++){
int rc2 = {random_integer};
if (rc2 == rg2){
sommarc2 = 5;
}
else{
sommarc2 = 0;
}
}
for(int i=0; i<n; i++){
int rc3 = {random_integer};
if (rc3 == rg3){
sommarc3 = 5;
}
else{
sommarc3 = 0;
}
}
for(int i=0; i<n; i++){
int rc4 = {random_integer};
if (rc4 == rg4){
sommarc4 = 5;
}
else{
sommarc4 = 0;
}
}
for(int i=0; i<n; i++){
int rc5 = {random_integer};
if (rc5 == rg5){
sommarc5 = 5;
}
else{
sommarc5 = 0;
}
}
for(int i=0; i<n; i++){
int rc6 = {random_integer};
if (rc6 == rg6){
sommarc6 = 5;
}
else{
sommarc6 = 0;
}
}
for(int i=0; i<n; i++){
int rc7 = {random_integer};
if (rc7 == rg7){
sommarc7 = 5;
}
else{
sommarc7 = 0;
}
}
for(int i=0; i<n; i++){
int rc8 = {random_integer};
if (rc8 == rg8){
sommarc8 = 5;
}
else{
sommarc8 = 0;
}
}
for(int i=0; i<n; i++){
int rc9 = {random_integer};
if (rc9 == rg9){
sommarc9 = 5;
}
else{
sommarc9 = 0;
}
}
for(int i=0; i<n; i++){
int rc10 = {random_integer};
if (rc10 == rg10){
sommarc10 = 5;
}
else{
sommarc10 = 0;
}
}
for(int i=0; i<n; i++){
int rc11 = {random_integer};
if (rc11 == rg11){
sommarc11 = 5;
}
else{
sommarc11 = 0;
}
}
for(int i=0; i<n; i++){
int rc12 = {random_integer};
if (rc12 == rg12){
sommarc12 = 5;
}
else{
sommarc12 = 0;
}
}
for(int i=0; i<n; i++){
int rc13 = {random_integer};
if (rc13 == rg13){
sommarc13 = 5;
}
else{
sommarc13 = 0;
}
}
for(int i=0; i<n; i++){
int rc14 = {random_integer};
if (rc14 == rg14){
sommarc14 = 5;
}
else{
sommarc14 = 0;
}
}
for(int i=0; i<n; i++){
int rc15 = {random_integer};
if (rc15 == rg15){
sommarc15 = 5;
}
else{
sommarc15 = 0;
}
}
for(int i=0; i<n; i++){
int rc16 = {random_integer};
if (rc16 == rg16){
sommarc16 = 5;
}
else{
sommarc16 = 0;
}
}
for(int i=0; i<n; i++){
int rc17 = {random_integer};
if (rc17 == rg17){
sommarc17 = 5;
}
else{
sommarc17 = 0;
}
}
for(int i=0; i<n; i++){
int rc18 = {random_integer};
if (rc18 == rg18){
sommarc18 = 5;
}
else{
sommarc18 = 0;
}
}
for(int i=0; i<n; i++){
int rc19 = {random_integer};
if (rc19 == rg19){
sommarc19 = 5;
}
else{
sommarc19 = 0;
}
}
for(int i=0; i<n; i++){
int rc20 = {random_integer};
if (rc20 == rg20){
sommarc20 = 5;
}
else{
sommarc20 = 0;
}
}
for(int i=0; i<n; i++){
int rc21 = {random_integer};
if (rc21 == rg21){
sommarc21 = 5;
}
else{
sommarc21 = 0;
}
}
for(int i=0; i<n; i++){
int rc22 = {random_integer};
if (rc22 == rg22){
sommarc22 = 5;
}
else{
sommarc22 = 0;
}
}
for(int i=0; i<n; i++){
int rc23 = {random_integer};
if (rc23 == rg23){
sommarc23 = 5;
}
else{
sommarc23 = 0;
}
}
for(int i=0; i<n; i++){
int rc24 = {random_integer};
if (rc24 == rg24){
sommarc24 = 5;
}
else{
sommarc24 = 0;
}
}
for(int i=0; i<n; i++){
int rc25 = {random_integer};
if (rc25 == rg25){
sommarc25 = 5;
}
else{
sommarc25 = 0;
}
}
//Ora calcolerò la somma totale delle risposte a caso.
sommarc = (tutte le sommarc che non scrivo altrimenti slargherebbe la pagina, ovvero sommarc1+sommarc2... fino a sommarc25)/n;
//Devo ancora dare il codice per la deviazione standard, ma non è un problema.
cout << "Il punteggio medio di n giocatori risulta: "; cout << sommarc << endl;
cin >> ferma;
return 0;
}
Supdario
10-01-2011, 00:01
La variabile random_integer non ti serve.
Il define mettilo fuori dal main, magari appena sotto gli include.
Poi quando vuoi ottenere un numero random, ti basta fare:
variabile = random_integer();
Se vuoi fare un vettore di dimensione definita ti basta fare:
int vettore[25];
Se poi le vuoi sommare ti basta fare un ciclo for, qualcosa del genere:
int somma = 0;
for (int i = 0; i < 25; i++)
{
somma += vettore[i];
}
giovanniverdelegno
10-01-2011, 14:51
Scusami, forse non mi sono spiegato bene. Guarda/ate un attimo ai 25 cicli for posti per le 25 domande. Ipoteticamente questi cicli servono a "incanalare" i vari 5 o 0 (risposta giusta o errata) in un determinato vettore per poi alla fine sommarli tutti quanti insieme per ottenere la media. Ho provato a fare qualcosa del genere, ma nel testo riportato precedentemente ciò non può avvenire, ho chiaramente sbagliato.
Ora nei for ho provato ad aggiungere un'altra piccola variante:
for(int i=0; i<n; i++){
int rc1 = rand();
if (rc1 == rg1){
sommarc1 = 5;
}
else{
sommarc1 = 0;
}
int vettore1[i];
for(int i=0; i<n; i++){
sommarc1 = vettore1[i];
}
}
Ma penso che anche questa abbia poco senso. Ovviamente questo nuovo implemento è stato aggiunto ad ognuno dei 25 for corrispondenti alle domande, ma non va bene, anche perché non ho la più pallida idea di come poterli sommare. Quindi ribadisco il mio problema, esasperando la vostra caritatevole pazienza; alla fine di ognuno dei cicli for per le 25 domande, dovrei trovare il modo per immagazzinare in un qualcosa (tipo vettore, ma non lo so) i 5 o gli 0 della medesima domanda. Per esempio, io decido di far giocare 100 giocatori: alla fine del primo for, relativo alla prima risposta a caso, ci dovrà essere questo qualcosa che memorizzi i risultati ottenuti, e così via per tutte le altre domande.
Come fare?
Grazie 10^3.
giovanniverdelegno
10-01-2011, 19:04
for(int i=0; i<n; i++){
r1 = var() ;
cout << r1 << endl;
int rc1 = {r1};
if (rc1 == rg1){
sommarc1 = 5;
}
else{
sommarc1 = 0;
}
cout << "rc1 ";cout << sommarc1 << endl;
int somma1 = 0;
for (int i=0; i<n; i++){
somma1 += sommarc1;
}
cout << "somma1 "; cout << somma1 << endl;
}
Ok, sono quasi all'arrivo. Fin qui ci siamo: sono riuscito a risolvere il problema del numero casuale. Ora, ringraziando il cielo, è casuale (yuhuuu) ogni volta. Non so come ringraziarvi.
Il problema ora è che quel "somma1", che poi dovrà andare a sommarsi con somma2, somma3, somma4....somma25, funziona, ma c'è un errore concettuale dietro. (Ah ho messo tutti quei cout per vedere che cosa fa, ovviamente li toglierò).
http://oi55.tinypic.com/xbad6g.jpg
Ok, penso che l'immagine parli da sé. Magari ci arriverò io a breve, ma non capisco come fare..
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.