使用權重控制隨機選取
水果 | 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; }
留言
張貼留言