Сгенерировать два случайных числа в одной строке кода?

Я столкнулся с довольно неожиданной проблемой, когда делал некоторые вещи для iOS со случайными числами.

Сравните это:

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;

Это случайная функция:

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

На мой взгляд, как a), так и b) должны давать случайные числа в диапазоне [-49,49]. Однако работает только а). б) производит только числа в диапазоне [-1, 1].

Кажется, что вторая случайная часть каждого вызова сначала разрешается, кэшируется, а затем повторно используется для первой части строки, независимо от верхней границы.

Может кто-нибудь объяснить и уточнить, почему б) не работает?


person Ricardo Sanchez-Saez    schedule 12.10.2012    source источник


Ответы (3)


Это проблема приоритета.

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

Такой же как

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

Это настолько частая проблема, что многие стандарты кодирования требуют заключения ?: конструкций в круглые скобки. Использовать этот:

int yOffset = randomIntWithUpperLimit(50) * (randomIntWithUpperLimit(2) ? 1 : -1);
person David Schwartz    schedule 12.10.2012

Это связано с ассоциативностью и приоритетом операторов. Что происходит, так это то, что вы оцениваете оба своих случайных числа, а затем выбираете между -1 и 1.

Вы, вероятно, захотите что-то вроде этого для B:

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

Это гарантирует, что вы выберете от 1 до -1, а затем умножите его на случайное число в диапазоне от 0 до 49.

person Will    schedule 12.10.2012

Приоритет оператора ?: ниже, чем оператора *

Используйте круглые скобки как это

randomIntWithUpperLimit(50) * (randomIntWithUpperLimit(2) ? 1:-1);
person tsionyx    schedule 12.10.2012