Generate a random number within range?
Possible Duplicate:
Generating Random Numbers in Objective-C
如何生成范围内的随机数?
- 副本-f.e.stackoverflow.com/questions/160890/…
- 你尝试过搜索吗?这个问题以前被问过很多次。此外,以下所有的答案都是错误的,因为rand不是一个好的RNG,需要播种。你应该用arc4random代替。
- @戴夫:不能保证rand()一定是坏的,只是不能保证它是好的。推荐arc4random而不知道其目的(如果有的话)是没有意义的。大多数初学者不做任何对发电机质量至关重要的事情。
- @杰瑞同意了。然而,初学者可能根本不知道自己需要播种,这是arc4random的好处之一。关于这个话题有很多讨论:google.com/search?Q=站点:stackoverflow.com+arc4random+rand
- 完全复制:stackoverflow.com/questions/2509679/…
- Dilbert的随机数生成器:stackoverflow.com/questions/84556/…
- 是的,我在stackoverflow和google上做了很多搜索,但我发现大多数答案都是0到n之间的随机数。
- 它可能是一个副本,但它有一个最好的答案,杰瑞。
这实际上比大多数人意识到的更难得到真正的正确:
1 2 3 4 5 6 7 8 9 10 11 12 13
| int rand_lim (int limit ) {
/* return a random number between 0 and limit inclusive.
*/
int divisor = RAND_MAX /(limit +1);
int retval ;
do {
retval = rand() / divisor ;
} while (retval > limit );
return retval ;
} |
仅使用%(或等同于/)来获取范围内的数字的尝试几乎不可避免地会产生歪斜(即,某些数字的生成频率会比其他数字更高)。
至于为什么使用%会产生歪斜的结果:除非您想要的范围是rand_max的除数,否则歪斜是不可避免的。如果你从小数字开始,很容易就能知道为什么。考虑拿10块糖果,试着把它平均分配给三个孩子。显然,这是不可能的——如果你把所有的糖果都分发出去,你能得到的最接近的是两个孩子得到三块糖果,其中一个得到四块。
对于所有的孩子来说,只有一种方法可以得到相同数量的糖果:确保你根本不分发最后一块糖果。
为了将这与上面的代码联系起来,让我们从1到10的糖果和1到3的孩子开始编号。最初的除法是说既然有三个孩子,我们的除数是三。然后,我们从桶里拿出一个随机的糖果,看它的数字,除以3,然后把它递给那个孩子——但是如果结果大于3(即,我们选了10号糖果),我们根本就不分发它——我们丢弃它,然后再挑选一个糖果。
当然,如果您使用的是C++的现代实现(即支持C++ 11或更新的一个),那么通常应该使用标准库中的一个EDCOX1和3个类。上面的代码与std::uniform_int_distribution最接近,但是标准库还包括uniform_real_distribution以及一些非均匀分布的类(伯努利、泊松、正态,可能还有一些我现在不记得的类)。
- 我很抱歉,但是我们!我最不想做的就是在试图得到一个随机数时,循环一个不确定数(谁知道,也许永远知道)。不管是否倾斜,我将采用更简单的解决方案,或者是表驱动的解决方案。
- @迈克尔:在你下结论之前先试试看。实际上,"不确定数"通常是1。除非你在一个非常紧密的循环中这样做(例如,用随机数填充一个向量),否则几乎不可能以比明显错误的版本更慢的速度来测量它。
- 这在技术上是正确的,但您有一个Gigo问题,从rand()开始。当极限不是rand_max的一个因素时,您似乎正在尝试纠正歪斜,使用模块划分方法,您的错误在limit / RAND_MAX的顺序上,直到limit接近RAND_MAX为止。问题从类似prng的rand()dwarf效果开始。你所付出的代价是引入一个无限制运行时间的非极端循环[irl它只运行一次,但我们在这里分道扬镳;-)]而你什么也得不到,因为兰德是垃圾开始。
- 不,不,我明白为什么其他人都错了,这是一个很好的解决办法。但是,我来自于一片被分割的土地,直到最近,这片土地的分割还很缓慢。再加上一个rand()调用,这个调用也有点慢(更不用说unrandom了,循环调用会让我胃部不舒服),你就可以看到我站在哪里了。乍一看,我也担心这可能不是决定性的,但事实确实如此。啊,只是要适应21世纪这里的编码。
- "仅使用%(或等价地,/)来获取范围内的数字的尝试几乎不可避免地会引入倾斜(即,某些数字的生成频率将高于其他数字)。"这对我来说是个新闻。我并不是说这是错误的(我应该和337K代表辩论谁),但我自己的研究中从来没有提到过这个事实,我也没有根据自己的偶然观察看到过任何问题。
- @Ukko:rand()可能很穷。再说一遍,它可能不是;我使用了一个实现,它是Mersenne Twister,这是相当不错的。
- @菲利普里根:倾斜来自于取模后的小余数。假设您的随机数生成器生成11个值0-10,然后使用这些数字mod 5给您一个介于0和4之间的数字。有两种方法可以得到3(3和8),但有三种方法可以得到0(0、5、10),因此最终结果并不一致。这是一个真正的效果,但我认为,在使用prng的其他更大的问题中,有一个问题已经消失了。
- @杰瑞和@ukko:谢谢你的解释。他们讲得很有道理。看来我还有点事要做。干杯!
- @杰里·科芬:我还是会说,即使使用了机器翻译发电机,这也不是一件正确的事情,即使你已经减少了gigo的问题。但我想,这真的是一个最冒犯您的编码敏感性的问题。
- @Jerry在Mac OS X上,Rand()很差。尤其是,最下面的12位进入一个循环。您至少应该使用random()。
- 好干杯,伙计
1 2 3 4
| int rand_range (int min_n , int max_n )
{
return rand() % (max_n - min_n + 1) + min_n ;
} |
分数:
1 2 3 4
| double rand_range (double min_n , double max_n )
{
return (double)rand()/RAND_MAX * (max_n - min_n ) + min_n ;
} |
- 这不会给出统一的分配(两个的权力除外)。
- 我知道,但它工作得很快,小范围的分布也可以。它有利于游戏编码。不管怎样,我应该把这个写在答案的某个地方。
- @奥利,谁在乎?请参见上述答案中Ukko的评论。如果您首先使用rand(),那么最小的歪斜量(对于max_n-min_n来说相对较小)是您最不担心的。
- @用户168715:因为这种方法不会映射到合适的随机数实现上,而这种倾斜可能很重要。
对于范围[最小值,最大值]内的整数值:
1 2
| double scale = (double) (max - min ) / RAND_MAX ;
int val = min + floor(rand() * scale ) |
我在obj-c中专门为一个iPhone项目写了这个:
1 2 3 4 5 6 7
| - (int) intInRangeMinimum:(int)min andMaximum:(int)max {
if (min > max) { return -1; }
int adjustedMax = (max + 1) - min; // arc4random returns within the set {min, (max - 1)}
int random = arc4random() % adjustedMax;
int result = random + min;
return result;
} |
使用:
1
| int newNumber = [aClass intInRangeMinimum:1 andMaximum:100]; |
加盐调味
- 这个解决方案仍然有模块化算法引入的歪斜。因为您使用的是arc4库,所以它为您提供了您想要的名为"arc4random_Uniform"的例程,该例程提供了适当的统一结果。只需将一行更改为int random=arc4random_uniform(adjustedmax);
1 2 3 4 5 6 7 8 9 10
| +(NSInteger)randomNumberWithMin:(NSInteger)min WithMax:(NSInteger)max {
if (min>max) {
int tempMax=max;
max=min;
min=tempMax;
}
int randomy=arc4random() % (max-min+1);
randomy=randomy+min;
return randomy;
} |
我在一个随机数相关的类中使用这个方法。对于我不需要的需求很有效,但在某种程度上可能有偏见。