我试图在-60和60之间使用arc4random获取一个随机数。我生成1到120之间的avnumber,然后减去60.
如果这是一行,只要数字是负数,我就会得到奇怪的结果。
//Loop illustrates point better.
while (1) {
//Gets garbage numbers approximately half the time (when random1 should be negative)
NSInteger random1 = 1 + (arc4random() %120) - 60;
NSLog (@"random1: %li", random1);
//Essentially same thing, but works fine.
NSInteger random2 = 1 + (arc4random() %120);
NSInteger random3 = random2 - 60;
NSLog (@"random2: %li random3: %li", random2, random3);
}
为什么会这样?
答案 0 :(得分:3)
我怀疑问题源于arc4random
在0和(2 ** 32)-1之间返回u_int32_t
(无符号32位整数)这一事实,但仅进行计算适用于有符号整数。
无论如何,在生成随机数时,最好使用arc4random_uniform
,这样可以避免代码的模偏差。这种偏见几乎不会被观察到,但是你应该使用:
NSInteger random = 1 + (NSInteger)arc4random_uniform(120) - 60;
或者,从技术上讲,如果你想要包含-60到60之间的数字,你应该使用:
NSInteger random = (NSInteger)arc4random_uniform(121) - 60;
答案 1 :(得分:1)
arc4random()
返回无符号整数,1 + (arc4random() %120) - 60;
被解释为无符号,然后分配给NSInteger random1
。
您可以将(arc4random() %120)
的返回值强制转换为有符号整数:
NSInteger random1 = 1 + (NSInteger)(arc4random() %120) - 60;
或将arc4random()
的中间结果存储在无符号整数中:
NSInteger r = (arc4random() %120);
NSInteger random1 = 1 + r - 60;
另请注意,arc4random手册页建议使用arc4random_uniform()
而不是模数构造:
arc4random_uniform()建议使用像``arc4random()%upper_bound''这样的结构,因为它避免了 当上限不是2的幂时,“模偏”。
答案 2 :(得分:0)
对于初学者arc4random()
,返回u_int32_t
无符号32位数。无符号数不能为负数,因此减去大于无符号值的数字会导致未指定的行为。
在第二种情况下,您将mod'ed值分配给可以具有负数的有符号整数。
正如@Rob在他的回答中所述,使用arc4random_uniform
代替mod'ing来获得范围以消除偏见。