سؤال

I've stumbled into a quite surprising problem while doing some iOS stuff with random numbers.

Compare these:

a)

int xOffsetSign = randomIntWithUpperLimit(2) ? 1:-1;
int yOffsetSign = randomIntWithUpperLimit(2) ? 1:-1;
int xOffset = randomIntWithUpperLimit(50) * xOffsetSign;
int yOffset = randomIntWithUpperLimit(50) * yOffsetSign;

b)

int xOffset = randomIntWithUpperLimit(50) * randomIntWithUpperLimit(2) ? 1:-1;
int yOffset = randomIntWithUpperLimit(50) * randomIntWithUpperLimit(2) ? 1:-1;

This is the random function:

static inline int randomIntWithUpperLimit(unsigned int upperLimit) {
    return arc4random_uniform(upperLimit);
}

In my mind, both a) and b) should produce random numbers in the [-49,49] range. However, only a) works. b) only produces numbers in the [-1, 1] range.

It seems that the second random part of each call gets resolved first, is cached, and then reused for the first part of the line, regardless of upper bound.

Can somebody explain and clarify why b) won't work?

هل كانت مفيدة؟

المحلول

It's a precedence problem.

int yOffset = randomIntWithUpperLimit(50) * randomIntWithUpperLimit(2) ? 1 : -1;

Is the same as

int yOffset = (randomIntWithUpperLimit(50) * randomIntWithUpperLimit(2)) ? 1 : -1;

This is such a frequent problem that many coding standards require parentheses around ?: constructs. Use this:

int yOffset = randomIntWithUpperLimit(50) * (randomIntWithUpperLimit(2) ? 1 : -1);

نصائح أخرى

This is to do with operator associativity and precedence. What is happening is that you are evaluating both of your random numbers and then choosing between -1 and 1.

You probably want something like this for B:

int xOffset = randomIntWithUpperLimit(50) * (randomIntWithUpperLimit(2) ? 1:-1);
int yOffset = randomIntWithUpperLimit(50) * (randomIntWithUpperLimit(2) ? 1:-1);

This will ensure you choose between 1 and -1 and then times it by a random number in the range 0 to 49.

The priority of ?: operator is lower then * operator

Use parentheses as this

randomIntWithUpperLimit(50) * (randomIntWithUpperLimit(2) ? 1:-1);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top