2017-01-26 5 views
0

Пустой проект. Код:arc4random_uniform, производящие очень большие значения при литье в поплавок

int i = 0; 
while (i < 8) { 
    float amount = 100-arc4random_uniform(200); 
    NSLog(@"amount: %f", amount); 
    i++; 
} 

Вход:

amount: 21.000000 
amount: 90.000000 
amount: 79.000000 
amount: 4294967296.000000 
amount: 39.000000 
amount: 4294967296.000000 
amount: 81.000000 
amount: 4294967296.000000 

4294967296,000000 явно вне диапазона 100 - ran(200) (псевдокод)

Если я не объявляю amount, как float и вместо того, чтобы использовать эту int не происходит.

Что здесь происходит?

+4

arc4random возвращает целое без знака. Перед тем, как выполнить вычитание, выделите его (подписи) целым или двойным. – Rob

+0

@Rob Спасибо! Есть ли интуитивный способ сказать, когда что-то будет подписано против без знака или мне просто нужно проверить документы. У меня не было формального обучения коду и я узнал все, что знаю, читая исходный код, поэтому я не знаю разницы между подписанным и unsigned на данный момент; Я предполагаю, что это связано с знаком ± * infront числа (или отсутствием там для «unsigned»). –

+1

Стандартный 32-разрядный 'int' может представлять значения между -2,147,483,648 и 2,147,483,647, но' unsigned int' может представлять только значения между 0 и 4 294 967 295 (т. Е. 2, поднятые до 32-й степени, минус 1). Поэтому, если вы вычитаете 1 из значения unsigned int, равного 0, поскольку он не может представлять -1, он обтекает до 4 294 967 295. Что касается того, как знать, единственное, что я могу предложить, это то, что если вы держите панель «Быстрая помощь» открытой слева, это упрощает подтверждение того, какой тип возвращает метод. И, к сожалению, вам просто нужно, разработчик, подтвердить подписность метода. – Rob

ответ

1

Как @rob указывает, arc4random_uniform возвращает 32-разрядный целочисленный тип без знака (uint32_t), то есть число, большее или равное нулю, никогда не будет отрицательным. Таким образом, компилятор вычисляет выражение 100-arc4random_uniform(200), ожидая, что результат также будет беззнаковым числом.

Если результат arc4random_uniform(200) в вашем примере кода превышает 100, то 100-arc4random_uniform(200) приведет к присвоению отрицательного числа типу данных, который не может выразить отрицательные числа, поэтому вы получите неожиданные результаты.

Вы можете указать компилятор, что вы хотите иметь дело с подписанными числами, а @rob предполагает, отбрасывая результат arc4random_uniform к знаковому числу (в данном случае float):

float amount = 100 - (float)arc4random_uniform(200); 

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

float amount = 100.0f - arc4random_uniform(200); 
Смежные вопросы