根据概率随机选择项目

时间:2013-07-04 10:20:32

标签: iphone ios random-sample

我有一系列元素。每个元素都附有一个概率值。让我们说我有一系列的苹果,红色,黄色,绿色,蓝色等等。

- (Apple *)pickRandomApple
{
    Apple *red = [Apple redApple];
    Apple *green = [Apple greenApple];
    Apple *yellow = [Apple yellowApple];
    Apple *blue = [Apple blueApple];

    red.probability = 0.23f;
    green.probability = 0.85f;
    yellow.probability = 0.1f;
    blue.probability = 0.5f;
    NSArray *array = @[red,green,blue,yellow];

    return array[arc4random()%array.count];
}

我想根据概率属性选择随机苹果。我怎样才能做到这一点?

谢谢!

3 个答案:

答案 0 :(得分:1)

一种可能的解决方案是将项目(概率*精度)次添加到数组中并在其上使用随机数。

否则,您可以总结概率并定义区域

double max = (red.probability + green.probability + yellow.probability 
+ blue.probability) * 100.f;

int random = arc4random()%(int)max;

if(random < red.probability * 100)
    return red;
else if(random < (red.probability + blue.probability) * 100)
    return blue:
...

等等。

也可以为此创建一个for循环:)

更新

double max = (red.probability + green.probability + yellow.probability 
+ blue.probability) * 100.f;
// max = (0.23 + 0.85 + 0.1 + 0.5) * 100; // = 1.68 * 100 = 168 

int random = arc4random()%(int)max;

if(random < red.probability * 100) // area 0 - 23
    return red;
else if(random < (red.probability + blue.probability) * 100) // area 24 - 108
    return blue:
...

并且在循环中你可以保存currentValue变量

double max = (red.probability + green.probability + yellow.probability 
+ blue.probability) * 100.f;
// max = (0.23 + 0.85 + 0.1 + 0.5) * 100; // = 1.68 * 100 = 168 

int random = arc4random()%(int)max;
int currentValue = 0;

for(Apple *apple in array)
{
    currentValue += (int)(apple.probability * 100.f);
    if(random <= currentValue)
        return apple;
}

只需尝试使用测试值,如果它不能正常工作,请告诉我你错过了什么:)

答案 1 :(得分:0)

我从你的问题中了解到你想要用强度生成概率,比如绿色更可能发生而不是红色......等等这个问题与iOS或iPhone开发无关,它是纯粹的编程问题和我不认为有一个解决方案。这是我的解决方案,我想通常使用简单的解决方案。

在发布代码之前,我想解释一下我的想法。这个问题类似于我们以前在高中学习的概率问题,所以我会以同样的方式解决它。我也会用你的号码。所以请考虑你有一个盒子里有23个红球,85个绿球,10个黄球和50个蓝球。所有这些球都在一个盒子里,你必须从盒子里随机选择一个球,因此红色的概率为0.23,绿色为0.85 ......

这是我的彩球盒:

char apples[] = {'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y', 'r', 'g', 'g', 'r', 'g', 'g', 'r', 'g'};

您注意到我使用特殊分布在阵列中分发了球。好吧,想象一下使用你的数字的方框示例。你有10个黄色球与85个绿色球,这意味着我希望在每个1个黄色球旁边的框中看到8个绿色球,并且以同样的方式我期望看到5个蓝色和2个红色。而且,由于格林最有可能,我希望首先看到它。因此,您可以看到我的数组具有以下模式:

'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'b', 'b', 'b', 'b', 'b', 'r', 'r', 'y',

每1个黄色,8个绿色,5个蓝色,2个红色。由于还有更多的红色和绿色,我在阵列的末尾添加了它们。

现在这个过程非常简单,因为这个集合包含168个球,我创建了一个运行168次的循环,每次生成一个从0到167的数字。我使用这个数字是数组的索引{{1}我看到了哪个球。

apples

以下是不同执行程序的示例输出:

int counters[4] = {0, 0, 0, 0};
int x;
for(int i=0; i<168; i++)
{
    x = arc4random()%168;
    if(apples[x] == 'r') counters[0]++;
    else if(apples[x] == 'g') counters[1]++;
    else if(apples[x] == 'y') counters[2]++;
    else if(apples[x] == 'b') counters[3]++;
}

NSLog(@"Red:    %i%%", counters[0]);
NSLog(@"Green:  %i%%", counters[1]);
NSLog(@"Yellow: %i%%", counters[2]);
NSLog(@"Blue:   %i%%", counters[3]);

您可以根据需要使用数组来增强效果。

答案 2 :(得分:0)

这是我的方法,它更通用一些。 随意提问/编辑

/**
 @param probabilitiesArray - array of integers who represent probabilities.
 If the first var in the array is 20 and the rest of the array's variables 
 sum up to 100 - there are 20% probability for first var to be chosen.
 */
-(int) randomNumberWithProbabilities:(NSArray *) probabilitiesArray
{
    //Sum up all the variables in the array
    int arraySum = 0;
    for(int i = 0;i < probabilitiesArray.count;i++)
    {
        arraySum += [probabilitiesArray[i] intValue];
    }

    //Random a number from 0 to the sum of the array variables
    int randomNumber = arc4random_uniform(arraySum);

    //Iterating through the array variable and detect the right slot for the random number
    int tempSum = 0;
    for(int i = 0;i < probabilitiesArray.count;i++)
    {
        tempSum += [probabilitiesArray[i] intValue];
        if(randomNumber < tempSum)
        {
            return i;
        }
    }
    return 0;
}