int chance = -5;
int rand = arc4random() % 100; // Number from 0 to 99
if (rand <= chance) { // This will never happen
NSLog(@"This is... NOT POSSIBLE");
}
实际上,这种情况从未发生过。但
int chance = -5;
if (arc4random() % 100 <= chance) {
NSLog(@"This is... NOT POSSIBLE");
}
这里,我将随机数表达式直接放在条件中,而不是将其存储在变量中。并且条件得以实现(有时)。
为什么?我该如何调试此行为?
答案 0 :(得分:6)
输入促销规则。
arc4random
会返回无符号值。这意味着在第二种情况下,-5
会被提升为相同的无符号类型,并将其转换为4294967291
。 4亿多肯定比任何数字都大0-99!
让我们来看看你们两个例子中发生的事情。
从第一个例子开始,在这一行:
int rand = arc4random() % 100;
arc4random()
返回无符号值。所以它看起来像:
int rand = someUnsignedNumber % 100;
100
是一个带符号的int,因此它会被提升为与someUnsignedNumber
相同的类型,并应用%
操作。之后你有:
int rand = someUnsignedNumberBetween0And99;
将无符号数分配给int rand
会使其返回到有符号数字。然后你的比较按预期进行。
在第二个例子中,你有这一行:
if (arc4random() % 100 <= chance)
同样的事情发生在arc4random() % 100
上,产生类似的东西:
if (someUnsignedNumberBetween0And99 <= chance)
但是在这里,chance
是签名号码。它会得到提升,如上所述改变它的价值,你最终会看到你所看到的奇怪行为。
答案 1 :(得分:5)
愚蠢的C型系统...如果您阅读arc4random()
的{{3}},就会发现它的原型是
u_int32_t arc4random(void);
因此它返回无符号整数。
当将其 - unsigned - result与另一个整数进行比较时,unsignedness“wins”:另一个值(-5
)被提升为无符号类型(在这种情况下为u_int32_t
),它会翻转(因为无符号整数“underflow”被设计成在C中这样工作 - 你将获得2 ^ 32 - 5
),因此发生了“错误的”(即表现为意外)比较。
当您明确地将值分配给int
(即已签名)变量时,由于比较是在两种签名类型之间,因此不会发生此促销,因此会对其进行评估。期望的。