您的位置:首页 > 其它

rand & random & arc4random

2015-01-27 14:32 309 查看

rand(3) / random(3) / arc4random(3) / et al.

Written by Mattt Thompson on August 12th, 2013

What passes for randomness is merely a hidden chain of causality.

In a mechanical universe of material interactions expressed through mathematical equations, it is unclear whether nature encodes an element of chance, or if it's a uniquely human way to reconcile uncertainty.

We can be sure of one thing, however: in the closed, digital universe of CPU cycles, processes, and threads, there is no true randomness, only pseudorandomness.

Pseudorandomness, is often implemented in a way very similar to a cryptographic hash, as a deterministic function that returns a value based on the current time (salted, of course, by some initial seed value). Also like hash functions, there are a number of PRNG, or pseudorandom number generators, each of which are optimized for particular performance characteristics: uniformity, periodicity, and computational complexity.

Of course, for app developers, all of this is an academic exercise. And rather than bore you with any more high-minded, long-winded treatises on the philosophical nature of randomness, we're going to tackle this one FAQ-style.

Our goal this week: to clear up all of the lingering questions and misunderstandings about doing random things in Objective-C. Let's dive in!

How Do I Generate a Random Number in Objective-C?

tl;dr: Use
arc4random()
and its related functions.


Specifically, to generate a random number between
0
and
N - 1
, use
arc4random_uniform()
, which avoids modulo bias.

Random
int
between
0
and
N - 1

Objective-C

NSUInteger r = arc4random_uniform(N);


Random
int
between
1
and
N

Objective-C

NSUInteger r = arc4random_uniform(N) + 1;


Random
double
between
0
and
1

If you are generating a random
double
or
float
, another good option is the more obscure
rand48
family of functions, including
drand48(3)
.

Objective-C

srand48(time(0));
double r = drand48();



rand48
functions, unlike
arc4random
functions, require an initial value to be seeded before generating random numbers. This seed function,
srand48(3)
, should only be run once.


How Do I Pick a Random Element from an
NSArray
?

Use
arc4random_uniform(3)
to generate a random number in the range of a non-empty array.

Objective-C

if ([array count] > 0) {
id obj = array[arc4random_uniform([array count])];
}


How Do I Randomly Order an
NSArray
?

Objective-C

NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
NSUInteger count = [mutableArray count];
// See http://en.wikipedia.org/wiki/Fisher–Yates_shuffle if (count > 1) {
for (NSUInteger i = count - 1; i > 0; --i) {
[mutableArray exchangeObjectAtIndex:i withObjectAtIndex:arc4random_uniform((int32_t)(i + 1))];
}
}

NSArray *randomArray = [NSArray arrayWithArray:mutableArray];



This code is borrowed from TTTRandomizedEnumerator, which also provides randomized enumerators for
NSSet
,
NSOrderedSet
, and
NSDictionary
.


How Do I Generate a Random String?

If you're looking to generate "lorem ipsum"-style sentences, try constructing a Markov Chain from a corpus.

Otherwise, if you're looking to just get random letters, try one of the following methods:

Generate a Random Lowercase
NSString

If you are operating on a known, contiguous range of Unicode characters, such as the lowercase letters (
U+0061
U+007A
), you can do a simple conversion from a
char
:

Objective-C

NSString *letter = [NSString stringWithFormat:@"%c", arc4random_uniform(26) + 'a'];


Pick a Random Character From an
NSString

Otherwise, a simple way to pick random letters from a set of your choosing is to simply create a string containing all of the possible letters:

Objective-C

NSString *vowels = @"aeiouy";
NSString *letter = [vowels substringWithRange:NSMakeRange(arc4random_uniform([vowels length]), 1)];


Why Should I Use
arc4random(3)
instead of
rand(3)
or
random(3)
?


C functions are typically denoted with a number
3
inside of parentheses, following the organizational convention of
man
pages
.



arc4random
does not require an initial seed (with
srand
or
srandom
), making it that much easier to use.

arc4random
has a range up to
0x100000000 (4294967296)
, whereas
rand
and
random
top out at
RAND_MAX = 0x7fffffff (2147483647)
.

rand
has often been implemented in a way that regularly cycles low bits, making it more predictable.

What are
rand(3)
,
random(3)
, and
arc4random(3)
, and Where Do They Come From?

rand
is a standard C function.

random
is defined as part of the POSIX standard.

arc4random
is provided on BSD and derived platforms.

If you have any additional questions about randomness on Objective-C, feel free to tweet @NSHipster. As always, corrections are welcome in the form of a pull request.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: