如何生成一个与目标C中的前一个不同的随机数[重复]

时间:2022-04-25 15:02:32

This question already has an answer here:

这个问题在这里已有答案:

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的行。