Question Générer des nombres aléatoires dans Objective-C


Je suis une tête Java principalement, et je veux un moyen de générer un nombre pseudo-aléatoire entre 0 et 74. En Java, j'utiliserais la méthode:

Random.nextInt(74)

Je ne suis pas intéressé par une discussion sur les graines ou le vrai hasard, juste comment vous accomplissez la même tâche dans Objective-C. J'ai parcouru Google, et il semble y avoir beaucoup d'informations différentes et contradictoires.


712
2017-10-02 04:35


origine


Réponses:


Vous devriez utiliser la fonction arc4random_uniform (). Il utilise un algorithme supérieur à rand. Vous n'avez même pas besoin de définir une graine.

#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);

La page de manuel arc4random:

NAME
     arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdlib.h>

     u_int32_t
     arc4random(void);

     void
     arc4random_stir(void);

     void
     arc4random_addrandom(unsigned char *dat, int datlen);

DESCRIPTION
     The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8
     bit S-Boxes.  The S-Boxes can be in about (2**1700) states.  The arc4random() function returns pseudo-
     random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and
     random(3).

     The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via
     arc4random_addrandom().

     There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically
     initializes itself.

EXAMPLES
     The following produces a drop-in replacement for the traditional rand() and random() functions using
     arc4random():

           #define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))

985
2017-10-02 16:00



Utilisez le arc4random_uniform(upper_bound) fonction pour générer un nombre aléatoire dans une plage. Ce qui suit va générer un nombre compris entre 0 et 73 inclus.

arc4random_uniform(74)

arc4random_uniform(upper_bound) évite polarisation modulo comme décrit dans la page de manuel:

arc4random_uniform () retournera un nombre aléatoire uniformément distribué inférieur à upper_bound. arc4random_uniform () est recommandé sur les constructions comme `` arc4random ()% upper_bound '' car il évite "polarisation modulo"quand la limite supérieure n'est pas une puissance de deux.


411
2017-08-16 17:47



Même que C, vous feriez

#include <time.h>
#include <stdlib.h>
...
srand(time(NULL));
int r = rand() % 74;

(en supposant que vous vouliez inclure 0 mais en excluant 74, ce que fait votre exemple Java)

Modifier: N'hésitez pas à substituer random() ou arc4random() pour rand() (ce qui est, comme d'autres l'ont souligné, assez sucky).


61
2017-10-02 04:45



J'ai pensé pouvoir ajouter une méthode que j'utilise dans de nombreux projets.

- (NSInteger)randomValueBetween:(NSInteger)min and:(NSInteger)max {
    return (NSInteger)(min + arc4random_uniform(max - min + 1));
}

Si je finis par l'utiliser dans de nombreux fichiers, je déclare généralement une macro comme

#define RAND_FROM_TO(min, max) (min + arc4random_uniform(max - min + 1))

Par exemple.

NSInteger myInteger = RAND_FROM_TO(0, 74) // 0, 1, 2,..., 73, 74

Note: Seulement pour iOS 4.3 / OS X v10.7 (Lion) et plus tard


43
2018-06-19 14:08



Cela vous donnera un point flottant nombre compris entre 0 et 47

float low_bound = 0;      
float high_bound = 47;
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);

Ou tout simplement

float rndValue = (((float)arc4random()/0x100000000)*47);

Les limites inférieure et supérieure peuvent être négatif ainsi que. L'exemple de code ci-dessous vous donne un nombre aléatoire compris entre -35,76 et +12,09

float low_bound = -35.76;      
float high_bound = 12.09;
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);

Convertir le résultat en un arrondi Entier valeur:

int intRndValue = (int)(rndValue + 0.5);

42
2018-02-16 11:47



Selon la page de manuel de rand (3), la famille de fonctions rand a été rendue obsolète par random (3). Cela est dû au fait que les 12 bits inférieurs de rand () passent par un cycle. Pour obtenir un nombre aléatoire, semez le générateur en appelant srandom () avec une graine non signée, puis appelez random (). Ainsi, l'équivalent du code ci-dessus serait

#import <stdlib.h>
#import <time.h>

srandom(time(NULL));
random() % 74;

Vous n'aurez besoin d'appeler srandom () qu'une fois dans votre programme, sauf si vous voulez changer votre graine. Bien que vous ayez dit que vous ne vouliez pas discuter de valeurs vraiment aléatoires, rand () est un générateur de nombres aléatoires assez mauvais, et random () souffre toujours du biais modulo, car il va générer un nombre entre 0 et RAND_MAX. Ainsi, par exemple si RAND_MAX est 3, et que vous voulez un nombre aléatoire entre 0 et 2, vous êtes deux fois plus susceptible d'obtenir un 0 qu'un 1 ou un 2.


34
2018-06-19 12:38



Mieux vaut utiliser arc4random_uniform. Cependant, ce n'est pas disponible ci-dessous iOS 4.3. Heureusement, iOS liera ce symbole lors de l'exécution, pas au moment de la compilation (n'utilisez donc pas la directive du préprocesseur #if pour vérifier si elle est disponible).

La meilleure façon de déterminer si arc4random_uniform est disponible est de faire quelque chose comme ceci:

#include <stdlib.h>

int r = 0;
if (arc4random_uniform != NULL)
    r = arc4random_uniform (74);
else
    r = (arc4random() % 74);

30
2018-01-28 00:02