使用權重控制隨機選取




水果  |  Apple  | Orange | Banana | Mango
------------------------------------------
權重  |   70    |   10   |   10   |   10

從這個表中,我們分派了各個權重,我們希望Apple最常被抽中,所以將權重設定較高的值。

因此我們從這個表來實現作法。


fruits = [[NSArray alloc] initWithObjects:@"apple",@"orange",@"banana",@"mango", nil];//定義水果

weights = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:70],[NSNumber numberWithInt:10],[NSNumber numberWithInt:10],[NSNumber numberWithInt:10], nil];
//定義權重

 int currentfruit=0;

    NSMutableArray *weighedfruits = [[NSMutableArray alloc] init];

        while (currentfruit<[fruits count]){ //step through each fruit[] element

       for (int i = 0; i < [[weights objectAtIndex:currentfruit] intValue]; i++) {
       
         [weighedfruits addObject: [fruits objectAtIndex:currentfruit]];
                

                }

            currentfruit++;

            if (currentfruit==[fruits count]) {//避免這個值超過水果的長度,導致Crash
                break;
            }
        }
   
     int randNum = arc4random() % 100 - 1; // 設定範圍值
    

    NSLog(@"%@",[weighedfruits objectAtIndex:randNum]);//即可看結果。

-----------------------------------------------------------------------------

後記,在一開始想要做可以透過權重來取得一些值,但是不知道為什麼腦袋就是一直轉不過來,不知道
權重的值表示的是什麼義意,找了很多其他的程式語言來看,也跟著做了但還是不明白其中的用意是什麼,
後來看了Javascript版的這個演算法,一個一個試後,終於明白,現終於可以把他寫到Objective-C
,真的是搞了好幾天現終於弄懂了。在這些代碼中,不難發現有一個把全部的權重加總起來,而常常看到
會寫取出某個權重再來把值加上去,常常看得不懂,但後來才知道用意,是指把權重設定了多少就是這些值
重覆的放到一個陣列裡,一直加到權重的總數為止。

在亂數的部份使用從範圍中選取某一個值。

int randNum = arc4random() % [最大值] + [最小值];


因此就再代碼寫成如下。原意是最小值是1 最大值是權重總值,但array的起始值是0,所以做了修改變成是
0~99;

int randNum = arc4random() % 100 - 1;




------------以下是參考的Javascript版的代碼-----------------------------

參考來源: http://uihacker.blogspot.com/

// our array of items
var fruits:Array = ['apple','orange','banana','mango'];
// our array of weights
var weights:Array = [20,10,40,30];
// pick a random fruit, based on weights, with bananas most likely to get picked
var myFruit:String = fruits[ randomIndexByWeights( weights ) ];

/**
 * Takes an array of weights, and returns a random index based on the weights
 */
private function randomIndexByWeights( weights:Array ) : int
{
 // add weights
 var weightsTotal:Number = 0;
 for( var i:int = 0; i < weights.length; i++ ) weightsTotal += weights[i];
 // pick a random number in the total range
 var rand:Number = Math.random() * weightsTotal;
 // step through array to find where that would be 
 weightsTotal = 0;
 for( i = 0; i < weights.length; i++ )
 {
  weightsTotal += weights[i];
  if( rand < weightsTotal ) return i;
 }
 // if random num is exactly = weightsTotal
 return weights.length - 1;
}


留言

這個網誌中的熱門文章

[心得] 圖解 微分、積分生活中的微積分-第一章

Objective-C的數學運算函式

c# 把List中重復的資料去掉