开发者

Why does this random number sometimes get set to -1?

开发者 https://www.devze.com 2023-01-10 04:46 出处:网络
Every now and again, the following comes out as -1 开发者_如何学Goint randomIndex = random() % [directionsArray count] - 1;

Every now and again, the following comes out as -1

开发者_如何学Goint randomIndex = random() % [directionsArray count] - 1;

The init method for this class is where directionsArray is created and srand() is called. It looks like this

- (id) initSprite
{
    if ( ( self = [super initSprite] ) ) {

        speed = 1;

        directionsArray = [[NSArray arrayWithObjects:STRING_CONSTANT, STRING_CONSTANT, nil] retain];
        srand(time(NULL));
        [self pickRandomDirection];


    }
    return self;
}

- (void) pickRandomDirection
{
    int randomIndex = random() % [directionsArray count] - 1; // This sometimes comes out as -1??
}

At the moment, I'm working around it by using abs(randomIndex), but that's cheating and I should probably know what's going on for future reference.


Because 0 - 1 equals -1.

    random() % [directionsArray count] - 1;

What if random() returns 0 here ? You get 0%[directionsArray count] - 1; which is -1, since % has precedence over -

Perhaps you want random() % ([directionsArray count] - 1);


Does % have precedence over -1? If it does then when the remainder is 0 minuses 1 will result in negative one.


Know your operator precedence. If in doubt, use parentheses:

int randomIndex = random() % ([directionsArray count] - 1);


I don't know why nobody else has mentioned this, but the solution (in your case) is actually to not subtract at all.

As you're probably aware, indexes are zero-based. Remainders likewise start at 0, and they go up to the divisor minus one and then loop around. Consider, for example, the case of count == 3:

  • 0 % 3 = 0
  • 1 % 3 = 1
  • 2 % 3 = 2
  • 3 % 3 = 0

Doing the division first, as Stephen Canon and Jonathan Fischoff already told you, will cause you to subtract 1 from these valid indexes, causing the problem you saw.

Doing the division second is not much better: It solves the problem of coming up with an index of -1, but you're still cutting off the last possible index:

  • 0 % (count - 1 = 2) = 0
  • 1 % 2 = 1
  • 2 % 2 = 0
  • 3 % 2 = 1

Notice how index 3 never comes up.

Divide only; cut out the subtraction.

Also, indexes are normally NSUInteger (an unsigned integral type, unlike int, which is signed) in Cocoa and Cocoa Touch.


Don't use random

Use arc4random instead.

Now that issue is solved, you're subtracting 1 from the randomization expression, which, in the case of arc4random % len returning 0, you'd be subtracting 1 from that, which is -1.


I'd recommend arc4random. It seems to be the easiest to use and best rnd available in the SDK.

arc4random() % [directionsArray count];
0

精彩评论

暂无评论...
验证码 换一张
取 消