2015-01-07 13 views
10

Sono stato con arc4random() e arc4random_uniform() e ho sempre avuto la sensazione che non era esattamente a caso, per esempio, ero casualmente valori scegliendo tra una vasta gamma ma spesso i valori che sono venuti sono stati gli stessi quando li ho generati più volte di seguito, quindi oggi ho pensato che avrei usato un parco giochi Xcode per vedere come si comportano queste funzioni, quindi prima testò arc4random_uniform per generare un numero compreso tra 0 e 4, quindi Ho usato questo algoritmo:arc4random() e arc4random_uniform() non sono casuali?

import Cocoa 

var number = 0 

for i in 1...20 { 
    number = Int(arc4random_uniform(5)) 
} 

E l'ho eseguito volte Veral, e qui è come i valori si stanno evolvendo la maggior parte del tempo:
enter image description here enter image description here

Quindi, come potete vedere i valori sono in aumento e in diminuzione più volte, e una volta che i valori sono al massimo/minimo, spesso ci rimani durante un certo tempo (vedi la prima schermata al quinto passaggio, il valore rimane a 3 durante 6 passaggi, il problema è che non è affatto insolito, la funzione si comporta in questo modo in gran parte del tempo nei miei test

Ora, se guardiamo arc4random(), è fondamentalmente lo stesso:
enter image description here enter image description here

Così qui sono le mie domande:

  • Perché questa funzione si comporta in questo modo?
  • Come renderlo più casuale?

Grazie.

EDIT:
Infine, ho fatto due esperimenti che sono stati sorprendenti, il primo con un vero e dadi:
enter image description here
Cosa mi ha sorpreso è che non avrei detto che è stata casuale, poiché stavo vedendo lo stesso tipo di schema che è descritto come non casuale per arc4random() & arc4random_uniform(), così come ha sottolineato Jean-Baptiste Yunès, gli umani non sono bravi a vedere se una sequenza di numeri è davvero casuale.

ho anche voluto fare un esperimento più "scientifica", così ho fatto questo algoritmo:

import Foundation 

var appeared = [0,0,0,0,0,0,0,0,0,0,0] 
var numberOfGenerations = 1000 

for _ in 1...numberOfGenerations { 
    let randomNumber = Int(arc4random_uniform(11)) 
    appeared[randomNumber]++ 
} 

for (number,numberOfTimes) in enumerate(appeared) { 
    println("\(number) appeard \(numberOfTimes) times (\(Double(numberOfGenerations)/Double(numberOfTimes))%)") 
} 

per vedere quante volte ogni numero è apparso, e in modo efficace i numeri sono generati casualmente, per esempio, ecco un output dalla console:
0 apparso 99 volte.
1 apparso 97 volte.
2 apparso 78 volte.
3 apparso 80 volte.
4 apparso 87 volte.
5 è apparso 107 volte.
6 apparso 86 volte.
7 apparso 97 volte.
8 è apparso 100 volte.
9 apparso 91 volte.
10 apparso 78 volte.

quindi è sicuramente OK

EDIT # 2: ho fatto di nuovo l'esperimento a dadi con più cilindri, ed è ancora così sorprendente per me:
enter image description here

+0

Controlla questo: http://stackoverflow.com/questions/56648/whats-the-best-way-to-shuffle-an-nsmutablearray – Mrunal

+0

@Mrunal Non stanno usando le stesse funzioni di me? –

+0

@Mrunal Il mio problema non riguarda come sostituire elementi in un array, ma solo come generare numeri veramente casuali. :) –

risposta

8

Una vera e propria sequenza casuale di numeri non può essere generato da un algoritmo. Possono solo produrre una sequenza pseudo-casuale di numeri (qualcosa che assomiglia a una sequenza casuale). Quindi, a seconda dell'algoritmo scelto, la qualità della "casualità" può variare. La qualità delle sequenze arc4random() viene generalmente considerata avere una buona casualità.

Non è possibile analizzare visivamente la casualità di una sequenza ... Gli esseri umani sono molto cattivi nel rilevare la casualità! Tendono a trovare qualche struttura dove non c'è. Niente fa davvero male nei tuoi diagrammi (tranne la rara sottosuccessione di 6 tre consecutivi, ma questa è casualità, a volte accadono cose insolite). Saresti sorpreso se avessi usato un dado per generare una sequenza e disegnare il suo grafico. Fai attenzione che un campione di soli 20 numeri non può essere analizzato seriamente contro la sua casualità, il tuo bisogno di campioni molto più grandi.

Se è necessario qualche altro tipo di casualità, è possibile provare a utilizzare lo pseudo-file /dev/random, che genera un numero casuale ogni volta che si legge. La sequenza è generata da un mix di algoritmi ed eventi fisici esterni che si verificano nel tuo computer.

+0

Quando mi hai detto che sarei sorpreso se avessi usato un dado ... beh, questo è esattamente quello che ho appena fatto, e sì, sono stato sorpreso: http://imgur.com/DZHfTUs Se avessi visto questo grafico e non sapevo che fosse un dado, avrei detto che si trattava di un cattivo generatore casuale. Ad ogni modo, sono comunque sorpreso che nelle mie generazioni casuali i valori sembrano essere vicini al massimo e al minimo della gamma di numeri che arc4random può generare, anche se non capisco esattamente cosa significa, potrei essere cercando come la sequenza di discrepanza di cui parla Jeffrey Thomas. –

+0

Ho fatto un algoritmo per vedere quante volte appare ogni numero, e questo è decisamente casuale! Ad esempio, per 1000 generazioni di numeri compresi tra 0 e 10, ho avuto: 0 visualizzato 101 volte (9,9009900990099%) 1 visualizzato 87 volte (11,4942528735632%) 2 visualizzato 79 volte (12,6582278481013%) 3 visualizzato 90 volte (11,1111111111111%) 4 appeard 95 volte (10,5263157894737%) 5 appeard 106 volte (9,43396226415094%) 6 appeard 90 volte (11,1111111111111%) 7 appeard 84 volte (11,9047619047619%) 8 appeard 78 volte (12,8205128205128%) 9 appeard 106 times (9.43396226415094%) 10 appeard 84 times (11.9047619047619%) –

+0

Ho modificato il mio post ... –

4

Dipende da cosa intendi quando parli a caso.

Come indicato nei commenti, la casualità vera è scomoda. Sono previste lunghe stringhe di ripetizioni o valori di chiusura.

Se questo non soddisfa i requisiti, è necessario definire meglio i requisiti.

Altre opzioni potrebbero includere l'utilizzo di un shuffle algorithm per disordinare le cose in un array o utilizzare un algoritmo low-discrepancy sequence per fornire una uguale distribuzione dei valori.

+0

Non riesco a capire esattamente quale sia una sequenza di discrepanze basse, è che se avessi usato una funzione del genere nel mio algoritmo, avrei ottenuto davvero molto velocemente altrettante 0 1, 2, 3 e 4? (per il mio arc4random_uniform (5))? –

+0

Ho modificato il mio post. –

+3

@ TrevörAnneDenise la sequenza di discrepanze basse ha l'aspetto di numeri casuali, ma ogni valore viene accuratamente selezionato per evitare la confusione. Per gli umani, sembra più casuale della casualità reale. –

Problemi correlati