2009-07-15 16 views
5

Gli do 0 e 400 e mi restituisce a volte valori superiori a 400. Questo non ha senso.Cosa c'è di sbagliato in questa funzione randomize?

- (float)randomValueBetween:(float)low andValue:(float)high { 
    return (((float) arc4random()/RAND_MAX) * (high - low)) + low; 
} 

che in realtà è uno snippet che ho trovato in rete. Forse qualcuno può vedere il bug lì dentro?

+0

Giusto per essere pedante, questo bug non ha molto a che fare con UIKit, iPhone, o (a malapena) Objective-C;) – jbrennan

+0

bene, per me ha;) – Thanks

risposta

7

Il manual page for arc4random indica che il valore restituito può essere compreso nell'intervallo valido per u int32 (ad esempio 0 to (2**32)-1). Ciò significa che dovrai dividere per 0xFFFFFFFF, anziché per RAND_MAX, che immagino sia inferiore (dipende comunque dalla libreria, quindi dovrai verificare esattamente di cosa si tratta).

La funzione dovrebbe diventare così:

- (float)randomValueBetween:(float)low andValue:(float)high { 
    return (((float) arc4random()/0xFFFFFFFFu) * (high - low)) + low; 
} 
+1

userei 'UINT32_MAX' piuttosto che la esplicita valore. –

+0

Sì, sembra che sia davvero arrabbiato '0xffffffffu'! – bobobobo

6
  • arc4random restituisce un valore pseudo-casuale da zero a (2^32 - 1)
  • RAND_MAX ha un valore predefinito di (2^31 - 1)

Quindi la funzione è probabilmente moltiplicando la gamma (high - low) fino a un fattore di 2, per i valori casuali nel la gamma 0 - 800.

3

Su iPhone, RAND_MAX è 0x7fffffff (2147483647), mentre arc4random() restituirà un valore massimo di 0x100000000, quindi (4294967296)/(2147483647) = 2 ..... 2 * (400-0) + 0 = 800! il valore massimo il metodo può tornare

0

Una variante più semplice potrebbe essere:

- (float)randomValueBetween:(float)low andValue:(float)high { 
    return (arc4random() % * (high - low)) + low; 
} 

Dal momento che si sta già facendo un'operazione mod perché non farlo direttamente sulla gamma di interessi?

Inoltre, perché passate in float (e restituendo float) se passate solo in numeri tondi? Gli integer sono più efficienti.

+0

Se la differenza tra 'high' e' low' è a virgola mobile allora è necessario chiamare ['fmodf()'] (http://developer.apple.com/library/ios/#documentation/System/Conceptual /ManPages_iPhoneOS/man3/fmodf.3.html) – bobobobo

Problemi correlati