This question already has an answer here:
这个问题在这里已有答案:
- Generating non-repeating random numbers 5 answers
生成非重复随机数5个答案
I have a int i generated from( arc4random() % 4), and then I create a new radon int q from another (arc4random() % 4), I wish q is generated until that is different from i.
我有一个从(arc4random()%4)生成的int i,然后我从另一个创建一个新的radon int q(arc4random()%4),我希望q生成,直到它与i不同。
For example, if i = 2, q must be 0, 1, 3.
例如,如果i = 2,则q必须为0,1,3。
How can I do that? Is there a loop or condition can be applied? Thanks
我怎样才能做到这一点?是否可以应用循环或条件?谢谢
5 个解决方案
#1
4
int q = (arc4random() % 4);
int i = (arc4random() % 4);
while (q == i) {
q = (arc4random() % 4);
}
#2
1
Use a while loop and store the previous result.
使用while循环并存储以前的结果。
For example,
int previous = (arc4random() % 4);
int current = (arc4random() % 4);
while(current == previous)
{
current = (arc4random() % 4);
}
#3
1
As some answers here have stated, arc4random
with a while loop, in general, is the right answer, but you likely want to use arc4random_uniform(x)
, as it avoids modulo bias.
正如这里的一些答案所述,带有while循环的arc4random通常是正确的答案,但你可能想要使用arc4random_uniform(x),因为它避免了模偏差。
From the docs:
来自文档:
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.
#4
0
int p = (arc4random() % 4);
int q = (arc4random() % 4);
while (p == q) {
p = (arc4random() % 4);
}
#5
0
I have found when I need randomness, it's nice to use a protocol so I can have random number generators of different flavors, yet not have to change any code when I change generators. With this approach, you can easily change the characteristic of your RNG.
我发现当我需要随机性时,使用协议很好,所以我可以使用不同风格的随机数生成器,但在更换生成器时不必更改任何代码。通过这种方法,您可以轻松更改RNG的特性。
If you wanted to prevent duplicates until all numbers have been used, you could substitute with a class that shuffled the values, then provided them until they were gone... shuffled again... etc. Of course, that approach only works if you have a small number of possible values. For much larger values a probabilistic approach would be necessary.
如果你想在使用所有数字之前防止重复,你可以用一个改组值的类替换,然后提供它们直到它们消失......再次洗牌......等等。当然,这种方法只适用于你有少量可能的值。对于更大的值,概率方法是必要的。
You would have this protocol somewhere...
你会在某个地方有这个协议......
@protocol RandomNumberGenerator <NSObject>
- (uint32_t)randomNumber;
@end
Then you could have this class, which provides a specific implementation of the protocol...
然后你可以拥有这个类,它提供了协议的特定实现......
@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
And then to use, you could make the RNG a property of your class, or make it generally available in some other manner...
然后使用,你可以让RNG成为你班级的财产,或者通常以其他方式使用它......
self.randomGenerator = [NonRepeatingRandomNumberGenerator initWithUpperBound:4];
Later, wherever you want a random number...
以后,无论你想要一个随机数...
randomNumber = [self.randomGenerator randomNumber];
If you ever decided to change how you wanted the numbers to be generated, you would simply replace the line that creates the RNG.
如果您决定更改生成数字的方式,则只需替换创建RNG的行。
#1
4
int q = (arc4random() % 4);
int i = (arc4random() % 4);
while (q == i) {
q = (arc4random() % 4);
}
#2
1
Use a while loop and store the previous result.
使用while循环并存储以前的结果。
For example,
int previous = (arc4random() % 4);
int current = (arc4random() % 4);
while(current == previous)
{
current = (arc4random() % 4);
}
#3
1
As some answers here have stated, arc4random
with a while loop, in general, is the right answer, but you likely want to use arc4random_uniform(x)
, as it avoids modulo bias.
正如这里的一些答案所述,带有while循环的arc4random通常是正确的答案,但你可能想要使用arc4random_uniform(x),因为它避免了模偏差。
From the docs:
来自文档:
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.
#4
0
int p = (arc4random() % 4);
int q = (arc4random() % 4);
while (p == q) {
p = (arc4random() % 4);
}
#5
0
I have found when I need randomness, it's nice to use a protocol so I can have random number generators of different flavors, yet not have to change any code when I change generators. With this approach, you can easily change the characteristic of your RNG.
我发现当我需要随机性时,使用协议很好,所以我可以使用不同风格的随机数生成器,但在更换生成器时不必更改任何代码。通过这种方法,您可以轻松更改RNG的特性。
If you wanted to prevent duplicates until all numbers have been used, you could substitute with a class that shuffled the values, then provided them until they were gone... shuffled again... etc. Of course, that approach only works if you have a small number of possible values. For much larger values a probabilistic approach would be necessary.
如果你想在使用所有数字之前防止重复,你可以用一个改组值的类替换,然后提供它们直到它们消失......再次洗牌......等等。当然,这种方法只适用于你有少量可能的值。对于更大的值,概率方法是必要的。
You would have this protocol somewhere...
你会在某个地方有这个协议......
@protocol RandomNumberGenerator <NSObject>
- (uint32_t)randomNumber;
@end
Then you could have this class, which provides a specific implementation of the protocol...
然后你可以拥有这个类,它提供了协议的特定实现......
@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
And then to use, you could make the RNG a property of your class, or make it generally available in some other manner...
然后使用,你可以让RNG成为你班级的财产,或者通常以其他方式使用它......
self.randomGenerator = [NonRepeatingRandomNumberGenerator initWithUpperBound:4];
Later, wherever you want a random number...
以后,无论你想要一个随机数...
randomNumber = [self.randomGenerator randomNumber];
If you ever decided to change how you wanted the numbers to be generated, you would simply replace the line that creates the RNG.
如果您决定更改生成数字的方式,则只需替换创建RNG的行。