2012-03-13 2 views
44

У меня есть два текстовых поля, и пользователь может ввести 2 положительных целых числа (используя Objective-C). Цель состоит в том, чтобы вернуть случайное значение между двумя числами.Генерировать случайные числа между двумя числами в Objective-C

Я использовал «man arc4random» и по-прежнему не могу полностью обвести вокруг себя голову. Я придумал какой-то код, но он глючит.

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)); 
} 

Прямо сейчас, если я вставляю значения 0 и 3, кажется, что все работает нормально. Однако, если я использую числа 10 и 15, я все равно могу получить значения как 1.0000000 или 2.000000 для «rndValue».

Нужно ли мне разработать свой алгоритм или мне нужно изменить способ использования arc4random?

+0

http://iphonedevelopment.blogspot.com/2008/10/random-thoughts-rand-vs-arc4random.html – Andrew

+1

Ваши круглые скобки ошибочны. Удалите открытую скобку после '*' и закрывающей круглой скобки перед ';'. Тем не менее, у вас все еще есть проблемы с округлением. –

+2

Общая формула 'minValue + ((maxValue - minValue) * rnd())' где 'rnd()' возвращает случайное значение с плавающей запятой между 0.0 и 1.0, вернет значение, которое вы ищете. Я оставляю это для вас, чтобы преобразовать это в Obj-C и оптимизировать его в соответствии с вашими потребностями. –

ответ

116

Вы могли бы просто использовать целые значения, как это:

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

Или, если вы имеете в виду вы хотите включить число с плавающей запятой между LowerBound и UpperBound? Если это так, пожалуйста, обратитесь к этому вопросу: https://stackoverflow.com/a/4579457/1265516

+1

int is not float – Andrew

+0

Извините, я неправильно понял ваш вопрос, пожалуйста, просмотрите обновленный ответ. – eveningsun

+2

код не включает upperBound в качестве случайного выхода, см. Мой ответ ниже в качестве исправления. – inexcii

57

Следующий код включает минимальное И МАКСИМАЛЬНУЮ значения в качестве случайного числа выхода:

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

Update:
Я редактировал ответ, заменив arc4random() % upper_bound с arc4random_uniform(upper_bound) как предложил @rmaddy.
И вот ссылка arc4random_uniform для деталей.

Update2:
Я обновил ответ, вставив литье в uint32_t в arc4random_uniform(), как указано на велосипеде.

+6

Еще лучше использовать 'return arc4random_uniform (max - min + 1) + min;'. – rmaddy

+0

@rmaddy Вы правы! Я обновил свой ответ и благодарю вас за это предложение. – inexcii

+0

Не хотите ли @Demasterpl получить результат с плавающей запятой? –

2

Вы должны избегать зажима значений с mod (%), если можете, потому что даже если генератор псевдослучайных чисел, который вы используете (например, arc4random), хорош для обеспечения равномерно распределенных номеров в полном диапазоне, это может не обеспечивают равномерно распределенные номера в ограниченном модульном диапазоне.

Вы также не должны использовать буквальный как 0x100000000 потому что удобно доступен в stdint.h постоянной:

(float)arc4random()/UINT32_MAX 

Это даст вам случайный поплавок в интервале [0,1] , Обратите внимание: arc4random возвращает целое число в интервале [0, 2 ** 32 - 1].

Чтобы переместить это в интервал вы хотите, вы просто добавить минимальное значение и умножить случайный поплавок размера вашего диапазона:

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

В коде вы публикуемыми вы умножая случайный поплавок по всему беспорядку (lowerBound + (upperBound - lowerBound)), который на самом деле просто равен upperBound. И именно поэтому вы по-прежнему получаете результаты меньше, чем ваша предполагаемая нижняя граница.

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

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) 
} 

Назовите это в любом месте:

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

Для Swift:

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

В Swift:

let otp = Int(arc4random_uniform(6)) 

Попробуйте это.