Go Down

Topic: Simulazione roulette (Read 1 time) previous topic - next topic

Stilita

#15
Apr 03, 2019, 02:36 pm Last Edit: Apr 03, 2019, 02:46 pm by Stilita
Intanto che cerco di capire dov'è l'errore, volevo illustrarvi il progetto:
Voglio che Arduino giochi da solo alla roulette, puntando sia sui numeri che sulle altre
caselle, però la puntata deve avvenire dopo che un numero o un colore ha raggiunto un certo ritardo.
Vi anticipo che la risposta  la so, perderà di media il 3% ad ogni puntata, perchè l'alea non ha memoria.
Lo stesso discorso varrebbe puntare sui numeri più frequenti...si perde, e sempre il 3%.

ps: il quel for incremento tutti i numeri, poi sottraggo una unità al numero estratto
quindi come se non l'avessi incrementato, poi lo confronto con il ritardo precedente e se quello attuale è maggiore aggiorno, poi visto che il numero è appena uscito gli azzero il ritardo...
Ho fatto una correzione, la "z" l'ho dichiarata globale, e non più locale, ma ancora non va

Code: [Select]
int x[37];   // incremento i ritardi
int y[37];   // ci metto i ritardi massimi
long c;
int rnd;
int z;
void setup() {
  randomSeed(analogRead(0));
  Serial.begin(9600);
  Serial.println("  ");
}
void loop() {
  c++;      //contatore
  if (c == 10000) {
    fine(); //limite conteggio
  }
  rnd = random(0, 37);   // genero un numero casuale da 0 a 36
  for ( z =0; z >= 36; z++) {
    x[z]++; //incremento il ritardo a tutti...
  }
  x[rnd]--;            //...tranne a quello estratto
  if (x[rnd] > y[rnd]) {
    y[rnd] = x[rnd];  // confronto il ritardo attuale del  numero estratto
    x[rnd] = 0;        //con il ritardo precedente ed eventualmente sostituisco
                        // e azzero il ritardo dell'ultimo estratto
  }
 
}
void fine() {
  for (int v = 0; v <= 36; v++) {
    Serial.print(v); Serial.print("  "); Serial.println(y[v]); // stampo tutti i numeri con il loro ritardo massimo
  }
}
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

fabpolli

Quello che ti hanno suggerito non aveva nulla a che fare con lo scope della variabile z, definirla globale in questo caso non serve a null, anzi.
Il problema è nel come hai scritto il for guardalo bene, se non ti salta all'occhio subito prova a guardare qui  ;)

Stilita

#17
Apr 03, 2019, 03:04 pm Last Edit: Apr 03, 2019, 03:04 pm by Stilita
Quello che ti hanno suggerito non aveva nulla a che fare con lo scope della variabile z, definirla globale in questo caso non serve a null, anzi.
Il problema è nel come hai scritto il for guardalo bene, se non ti salta all'occhio subito prova a guardare qui  ;)

In effetti la "z" non la uso più e poteva benissimo essere dichiarata dentro, mi sto scervellando
il for sembra giusto...aspettate un altro po a suggerire altrimenti verrò squalificato (cit. R. Petri)
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

fabpolli

#18
Apr 03, 2019, 03:17 pm Last Edit: Apr 03, 2019, 03:18 pm by fabpolli
Altro indizio il for NON è giusto, se tu avessi guardato il codice presente nel link che ti ho proposto e tu lo avessi confrontato con il tuo for dovresti notarla al volo la differenza tra il tuo e quello del reference

Stilita

#19
Apr 03, 2019, 03:24 pm Last Edit: Apr 03, 2019, 03:59 pm by Stilita
Ok, ci sono arrivato.
Retaggi di Basic, il cui for "ragiona" diversamente...

Grazie per lo sprono, per quando riguarda la funzione random, l'articolo di Leo per
me è un po ostico, allora farei così:
All'avvio moltiplico A0*A1 che al massimo mi da 1.046.529
poi lo divido per esempio 105 ed ottengo dei millisecondi che andrò a mettere in un delay
che farà partire il programma dopo alcuni secondi dall'accensione, ma nel frattempo millis() si
sta già incrementando per i fatti suoi, quando il delay finisce la funzione random l'aggangio a millis()
che nel frattempo ha maturato un numero diverso da 0.
Può essere un po più casuale di quella standard?

...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

gpb01

#20
Apr 03, 2019, 05:49 pm Last Edit: Apr 03, 2019, 05:52 pm by gpb01
....  per quando riguarda la funzione random, l'articolo di Leo per me è un po ostico ...
... ma guarda che NON occorre capire bene l'articolo per usare la libreria :D

La si include come tutte le altre:

Code: [Select]
#include "pRNG.h"
... la si istanzia come si fa per altre librerie:

Code: [Select]
pRNG prng;
... e quando serve un numero random si chiama il metodo che lo resistuisce (in realtà ci sono tre metodi per avere un numero long, int o byte, basta chiamare quello che veramente serve):

Code: [Select]
myLong = prng.getRndLong();
...
myInt  = prng.getRndInt();
...
myByte = prng.getRndByte();

Guglielmo

P.S.: Come detto occorre solo prestare attenzione a quanto è vecchia la propria scheda Arduino ... i vecchi bootloaders NON gestivano bene il WatchDog che questa libreria usa ed andavano in loop perenne.
Search is Your friend ... or I am Your enemy !

Stilita

#21
Apr 04, 2019, 07:19 am Last Edit: Apr 04, 2019, 07:29 am by Stilita
Code: [Select]
[quote author=gpb01 link=msg=4123084 date=1554306599]
... ma guarda che NON occorre capire bene l'articolo per usare la libreria ...



Ho provato, ma sorti 2 problemi:
Va in loop, devo provare quindi a caricare il nuovo bootloader.
Poi non so dove inserire l'intervallo dei numeri da generare, l'ho messo come in linea 18 ma mi da errore.
Code: [Select]
#include "pRNG.h"
pRNG prng;
unsigned long x[37];   // incremento i ritardi
unsigned long y[37];   // ci metto i ritardi massimi
unsigned long c;
int rnd;
int z;

void setup() {
  Serial.begin(9600);
  Serial.println(" prova ");
}
void loop() {
  c++;      //contatore
  if (c == 1000) {
    fine(); //limite conteggio
  }
  rnd = prng.getRndByte(0,37);   // genero un numero casuale da 0 a 36
  for ( z =0; z <= 36; z=z+1) {
    x[z]++; //incremento il ritardo a tutti...
  }
  x[rnd]--;            //...tranne a quello estratto
  if (x[rnd] > y[rnd]) {
    y[rnd] = x[rnd];  // confronto il ritardo attuale del  numero estratto
    x[rnd] = 0;        //con il ritardo precedente ed eventualmente sostituisco
                        // e azzero il ritardo dell'ultimo estratto
  }
 
}
void fine() {
  for (int v = 0; v <= 36; v++) {
    Serial.print(v); Serial.print("  "); Serial.println(y[v]); // stampo tutti i numeri con il loro ritardo massimo
  }
}
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

gpb01

#22
Apr 04, 2019, 07:36 am Last Edit: Apr 06, 2019, 03:37 pm by gpb01
Poi non so dove inserire l'intervallo dei numeri da generare, l'ho messo come in linea 18 ma mi da errore.
Perché NON puoi specificare direttamente l'intervallo ...

Quote
La libreria fornisce 3 metodi, getRndByte() per estrarre dal pool un byte casuale (0..255),  getRndInt() per estrarre un intero senza segno (0..65535), e getRndLong() per estrarre un intero lungo senza segno (0..4294967295)
... dopo di che, scelto il valore che ti interessa (es. byte o intero) applichi la funzione map() per rimappare il valore ottenuto all'interno dei tuoi limiti.

Guglielmo
Search is Your friend ... or I am Your enemy !

Stilita

#23
Apr 04, 2019, 08:41 am Last Edit: Apr 04, 2019, 08:41 am by Stilita
Ho rimappato, va bene, noto solo che la generazione dei numeri è diventata lentissima rispetto
a prima, è normale così ?

Code: [Select]
#include "pRNG.h"
pRNG prng;
unsigned long x[37];   // incremento i ritardi
unsigned long y[37];   // ci metto i ritardi massimi
unsigned long c;
int rnd;
int z;

void setup() {
  Serial.begin(9600);

  Serial.println("   ");
}
void loop() {
  c++;      //contatore
  if (c == 100) {
    fine(); //limite conteggio
  }
  rnd = prng.getRndByte(); // genero un numero casuale da 0 a 255
  rnd = map(rnd, 0, 255, 0, 36); // lo rimappo da 0 a 36
  //Serial.println(rnd);// segnalino per vedere i numeri generati
  for ( z = 0; z <= 36; z = z + 1) {
    x[z]++; //incremento il ritardo a tutti...
  }
  x[rnd]--;            //...tranne a quello estratto
  if (x[rnd] > y[rnd]) {
    y[rnd] = x[rnd];  // confronto il ritardo attuale del  numero estratto
    x[rnd] = 0;        //con il ritardo precedente ed eventualmente sostituisco
    // e azzero il ritardo dell'ultimo estratto
  }

}
void fine() {
  for (int v = 0; v <= 36; v++) {
    Serial.print(v); Serial.print("  "); Serial.println(y[v]); // stampo tutti i numeri con il loro ritardo massimo
  }
}
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

gpb01

Ho rimappato, va bene, noto solo che la generazione dei numeri è diventata lentissima rispetto
a prima, è normale così ?
La cosa è spiegata nell'articolo di leo72:

Quote
Una nota a riguardo del pool di numeri. Esso ha una dimensione che varia in base al quantitativo di SRAM del microcontrollore: si parte da 8 byte per le MCU con meno di 512 byte fino ad arrivare ai 16 byte delle MCU con più di 1024 byte. Esso viene popolato bit per bit a partire da quello meno significativo del primo byte fino al bit più significativo dell'ultimo byte. Una volta raggiunta l'estremità del pool, l'algoritmo riparte dall'inizio. Quando si estrae un byte, viene prelevato il primo byte dal pool e tutti quelli successivi vengono spostati indietro di una posizione per occupare lo spazio vuoto che si è creato. Se nel pool non sono disponibili almeno 8 bit, verrà atteso finché non sarà pronto 1 byte di entropia. Questa cosa è da tenere a mente perché richieste continuative di numeri casuali saranno evase solo quando i dati saranno disponibili. Il WatchDog Timer è impostato con il minimo prescaler possibile, che genera un interrupt circa ogni 16 millisecondi, per cui per ottenere 1 byte di entropia sono necessari circa 16 x 16 = 256 ms su un Atmega328.
Guglielmo
Search is Your friend ... or I am Your enemy !

Standardoil

Alcune libere considerazioni:
Come dice il mio socio il ritardo "massimo" è un'informazione poco significativa, dato che si limita ad aumentare sempre. Ma comunque se è quello che vuoi sapere....
Poi, tu prima di tutto devo essere sicuro che i numeri che prendi in esame siano realmente casuali, mica di avere in mezzo errori o sviste che ad un primo esame sfuggono, e questo ti è già capitato. Col primo che hai postato
Quindi io direi che come minimo dovresti registrare almeno il numero di estrazioni per ogni valore, per controllare che la distribuzione sia corretta, e magari anche il ritardo medio, per accorgersi di eventuali anomalie nei ritardo
Optimum sarebbe registrare su sd l'intero set di estrazioni, per futuri riscontri
Prima legge di Nelson (che sono io): Se vuoi il mio aiuto dimostrami almeno che hai letto il nostro "aiutateCi ad aiutarVi"

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

Stilita

#26
Apr 04, 2019, 09:18 am Last Edit: Apr 04, 2019, 09:32 am by Stilita
Io volevo  applicare la legge dei grandi numeri, che è la più attendibile, fare ad esempio 10.000.000
di estrazioni e vedere i ritardi per farmi un'idea, anche su pari e dispari...ecc.
Con la libreria per fare 100 estrazioni ci mette alcuni secondi, figurarsi milioni...
Questa libreria sarà utile a regime, una volta conosciuti i ritardi, quando Arduino comincerà a giocare da solo  tenendo conto dei ritardi .
Però è un cane che si morde la coda, perchè quando comincerà a giocare da solo usando la libreria non arriverà mai a milioni di estrazioni proprio per quel ritardo intrinseco nella funzione
...mumble mumble  :smiley-confuse:
Converrà usare il metodo lento, ma più affidabile , sia per calcolare i ritardi che per giocare, magari ponendo un limite più basso, diciamo 10.000 estrazioni per calcolare i ritardi.
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

Patrick_M

lol ... secondo me non arrivi da nessuna parte... :)
per inserire (lo sketch) il programma, dall'IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

SukkoPera

#28
Apr 04, 2019, 12:41 pm Last Edit: Apr 04, 2019, 12:42 pm by SukkoPera
Se i numeri generati sono veramente casuali con distribuzione uniforme (non conosco la libreria), vedrai che i ritardi non assumono alcun valore particolarmente utile. Immagino tenderanno tutti a un valore costante.

Se non è così, è un problema del generatore di numeri, non è assolutamente un'informazione significativa per il gioco, visto che i singoli lanci sono eventi indipendenti e quindi il risultato di uno non influenza in alcun modo gli altri, ma sembra che siamo tutti consci di questo :).
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

docdoc

#29
Apr 04, 2019, 01:19 pm Last Edit: Apr 04, 2019, 01:22 pm by docdoc
Mi stavo chiedendo su per giù che ritardo poteva avere un numero estratto alla roulette, in questo caso su 10000 estrazioni, ho tirato giù uno schetch, ma alla fine mi da tutti 0.
Non capisco se è un esercizio di programmazione, o se è proprio una tua curiosità matematico-statistica.

Nel primo caso ok ma resta sempre che devi considerare la "bontà" del generatore di numeri (pseudo)casuali utilizzato. Su Arduino (ma questa cosa vale per tantissimi altri sistemi analoghi) la Random() genera una sequenza pseudo-casuale partendo da un primo valore, detto "seme" o "seed". Quindi stesso seed = stessa sequenza. Dato che in genere come "seed" si prende il valore flottante di un pin analogico, ecco che su Arduino hai un massimo di 1024 sequenze diverse. Non propriamente "casuale" non ti pare? Ovviamente la cosa migliora utilizzando la libreria di leo72 che stando a quanto ho potuto vedere sfrutta il meccanismo dei registri a scorrimento lineari (non entro nel dettaglio, sappi che questi metodi sono anche alla base dei metodi di cifratura), anche se va considerato che anche per questi c'è un rischio ciclicità o ripetizioni (questa è una delle vulnerabilità di alcuni metodi di cifratura) per cui potrebbero essere comunque di fatto non del tutto "casuali".

Nel secondo caso invece la risposta la devi cercare nella matematica-statistica, più che con esperimenti (tanto più se questi hanno altre potenziali variabilità che possono influire anche pesantemente sul risultato). E la risposta è banale per chi studia matematica, e maubarzi te l'ha data: "infinito". Comunque allo stesso modo si può fare una statistica "fisica" anche più semplicemente sui numeri di un dado a 6 facce.
In sostanza il ritardo massimo è teoricamente infinito, quindi non ha senso porsi il problema, lo spiego meglio qui sotto:

Se i numeri generati sono veramente casuali con distribuzione uniforme (non conosco la libreria), vedrai che i ritardi non assumono alcun valore particolarmente utile. Immagino tenderanno tutti a un valore costante.
Se parli di probabilità si, teoricamente (come dici, con un generatore teorico uniforme di numeri casuali) la "frequenza relativa" con "n" eventi, o F(n), è pari al numero di estrazioni positive diviso per il numero totale di estrazioni, e all'aumentare di "n" si avvicina ad un valore pari alla probabilità teorica p(n) ossia 1/37 = 0.027 periodico. Raggiungendolo però solamente con INFINITE estrazioni (ossia n che tende ad infinito).

La domanda però era sul "ritardo" massimo, e questo invece è indefinito ossia poiché non esiste alcuna "memoria" nella roulette (come in altri giochi) delle estrazioni precedenti, ad ogni lancio la probabilità che esca un certo numero sono sempre del 2.7% il che significa che teoricamente potresti fare anche 1 milione di lanci, senza mai vedere un certo numero.

Questo, per farla semplice, perché seppure la probabilità media teorica sia 0.027, la distribuzione è una curva "a campana" con il valore massimo su 0.027 ma che si estende all'infinito seppure con valori sempre più prossimi allo zero.

Quindi la risposta al "ritardo massimo" di un numero è "infinito" ma potendo misurare moltissime estrazioni il "ritardo medio" tenderà ad avvicinarsi al numero di elementi ossia 37 (o 6 per il dado).
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

Go Up