【发布时间】:2014-03-25 12:14:50
【问题描述】:
我有一个从 (arc4random() % 4) 生成的 int i,然后我从另一个 (arc4random() % 4) 创建了一个新的氡气 int q,我希望生成 q 直到它与 i 不同。
例如,如果 i = 2,则 q 必须为 0、1、3。
我该怎么做?是否可以应用循环或条件? 谢谢
【问题讨论】:
标签: objective-c random
我有一个从 (arc4random() % 4) 生成的 int i,然后我从另一个 (arc4random() % 4) 创建了一个新的氡气 int q,我希望生成 q 直到它与 i 不同。
例如,如果 i = 2,则 q 必须为 0、1、3。
我该怎么做?是否可以应用循环或条件? 谢谢
【问题讨论】:
标签: objective-c random
int q = (arc4random() % 4);
int i = (arc4random() % 4);
while (q == i) {
q = (arc4random() % 4);
}
【讨论】:
使用while循环并存储之前的结果。
例如,
int previous = (arc4random() % 4);
int current = (arc4random() % 4);
while(current == previous)
{
current = (arc4random() % 4);
}
【讨论】:
正如这里的一些答案所述,带有 while 循环的 arc4random 通常是正确答案,但您可能希望使用 arc4random_uniform(x),因为它可以避免模数偏差。
来自文档:
arc4random_uniform() will return a uniformly distributed random number less than upper_bound.
arc4random_uniform() is recommended over constructions like ``arc4random() % upper_bound'' as it
avoids "modulo bias" when the upper bound is not a power of two.
【讨论】:
int p = (arc4random() % 4);
int q = (arc4random() % 4);
while (p == q) {
p = (arc4random() % 4);
}
【讨论】:
我发现当我需要随机性时,使用协议很好,这样我就可以拥有不同风格的随机数生成器,而在更改生成器时不必更改任何代码。通过这种方法,您可以轻松更改 RNG 的特征。
如果你想在所有数字都用完之前防止重复,你可以用一个打乱值的类来代替,然后提供它们直到它们消失……再次打乱……等等。当然,这种方法只是如果您有少量可能的值,则可以使用。对于更大的值,需要使用概率方法。
你会在某个地方有这个协议......
@protocol RandomNumberGenerator <NSObject>
- (uint32_t)randomNumber;
@end
然后你可以有这个类,它提供了协议的特定实现......
@interface NonRepeatingRandomNumberGenerator : NSObject<RandomNumberGenerator>
- (instancetype)init;
- (instancetype)initWithUpperBound:(uint32_t)upperBound;
- (uint32_t)randomNumber;
@end
@implementation NonRepeatingRandomNumberGenerator {
uint32_t lastNumber_;
uint32_t *upperBound_;
}
- (instancetype)init
{
if (self = [super init]) {
lastNumber_ = arc4random();
upperBound_ = NULL;
}
return self;
}
- (instancetype)initWithUpperBound:(uint32_t)upperBound
{
if (self = [super init]) {
lastNumber_ = arc4random_uniform(upperBound);
upperBound_ = malloc(sizeof(*upperBound_));
*upperBound_ = upperBound;
}
return self;
}
- (void)dealloc
{
free(upperBound_);
}
- (uint32_t)randomNumber
{
uint32_t result;
do {
result = upperBound_ ? arc4random_uniform(*upperBound_) : arc4random();
} while (result != lastNumber_);
lastNumber_ = result;
return result;
}
@end
然后使用,您可以使 RNG 成为您的类的属性,或者以其他方式使其普遍可用...
self.randomGenerator = [NonRepeatingRandomNumberGenerator initWithUpperBound:4];
以后,随便找个随机数……
randomNumber = [self.randomGenerator randomNumber];
如果您决定更改生成数字的方式,只需替换创建 RNG 的行。
【讨论】: