web-dev-qa-db-fra.com

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

J'ai deux zones de texte et l'utilisateur peut entrer 2 entiers positifs (en utilisant Objective-C). Le but est de renvoyer une valeur aléatoire entre les deux nombres.

J'ai utilisé "man arc4random" et je n'arrive toujours pas à m'envelopper la tête. J'ai trouvé du code mais c'est buggé.

float lowerBound = lowerBoundNumber.text.floatValue;
float upperBound = upperBoundNumber.text.floatValue;
float rndValue;
//if lower bound is lowerbound < higherbound else switch the two around before randomizing.
if(lowerBound < upperBound)
{
    rndValue = (((float)arc4random()/0x100000000)*((upperBound-lowerBound)+lowerBound));
}
else 
{
    rndValue = (((float)arc4random()/0x100000000)*((lowerBound-upperBound)+upperBound));
}

En ce moment, si je mets les valeurs 0 et 3, cela semble fonctionner très bien. Cependant, si j'utilise les nombres 10 et 15, je peux toujours obtenir des valeurs aussi faibles que 1,0000000 ou 2.000000 pour "rndValue".

Dois-je élaborer mon algorithme ou dois-je changer la façon dont j'utilise arc4random?

49
Demasterpl

Vous pouvez simplement utiliser des valeurs entières comme ceci:

int lowerBound = ...
int upperBound = ...
int rndValue = lowerBound + arc4random() % (upperBound - lowerBound);

Ou si vous voulez inclure un nombre flottant entre lowerBound et upperBound? Si oui, veuillez vous référer à cette question: https://stackoverflow.com/a/4579457/1265516

122
eveningsun

Le code suivant inclut la valeur minimale ET MAXIMUM comme numéro de sortie aléatoire:

- (NSInteger)randomNumberBetween:(NSInteger)min maxNumber:(NSInteger)max
{
    return min + arc4random_uniform((uint32_t)(max - min + 1));
}

Mise à jour:
J'ai modifié la réponse en remplaçant arc4random() % upper_bound par arc4random_uniform(upper_bound) comme l'a suggéré @rmaddy.
Et voici la référence de arc4random_uniform pour les détails.

Update2:
J'ai mis à jour la réponse en insérant un transtypage en uint32_t dans arc4random_uniform() comme indiqué @bicycle.

65
inexcii
-(int) generateRandomNumberWithlowerBound:(int)lowerBound
                               upperBound:(int)upperBound
{
    int rndValue = lowerBound + arc4random() % (upperBound - lowerBound);
    return rndValue;
}
7
Abo3atef

Vous devriez éviter de bloquer les valeurs avec mod (%) si vous le pouvez, car même si le générateur de nombres pseudo-aléatoires que vous utilisez (comme arc4random) est bon pour fournir des nombres uniformément distribués dans toute sa gamme, il peut ne pas fournir des nombres uniformément distribués dans la gamme modulo restreinte.

Vous n'avez pas non plus besoin d'utiliser un littéral comme 0x100000000 car il existe une constante pratique disponible dans stdint.h:

(float)arc4random() / UINT32_MAX

Cela vous donnera un flottant aléatoire dans l'intervalle [0,1]. Notez que arc4random renvoie un entier dans l'intervalle [0, 2 ** 32 - 1].

Pour déplacer cela dans l'intervalle souhaité, il vous suffit d'ajouter votre valeur minimale et de multiplier le flottant aléatoire par la taille de votre plage:

lowerBound + ((float)arc4random() / UINT32_MAX) * (upperBound - lowerBound);

Dans le code que vous avez publié, vous multipliez le flottant aléatoire par l'ensemble du désordre (lowerBound + (upperBound - lowerBound)), qui est en fait juste égal à upperBound. Et c'est pourquoi vous obtenez toujours des résultats inférieurs à votre limite inférieure prévue.

2
Aaron Golden

Fonction Objective-C:

-(int)getRandomNumberBetween:(int)from to:(int)to
{
    return (int)from + arc4random() % (to-from+1);
}

Swift:

func getRandomNumberBetween(_ from: Int, to: Int) -> Int 
{
    return Int(from) + arc4random() % (to - from + 1)
}

Appelez-le n'importe où par:

int OTP = [self getRandomNumberBetween:10 to:99];
NSLog(@"OTP IS %ld",(long)OTP);
NSLog(@"OTP IS %@",[NSString stringWithFormat @"%ld",(long)OTP]);

Pour Swift:

var OTP: Int = getRandomNumberBetween(10, to: 99)
0
Raj Aryan

Dans Swift:

let otp = Int(arc4random_uniform(6))

Essaye ça.

0
user9260747