Reputation: 1883
I have 3 IPs and every IP has a weight, I want to return the IP's according to its weights using the random function,,,, for example if we have 3 IP's : X with weight 6,Y with weight 4 and Z with weight 2, I want to return X in 50% of cases and Y in 33% of cases and Z in 17% of cases, depending on random function in C.
This code is to the case of 3 IPs:
double r = rand() / (double)RAND_MAX;
double denom = 6 + 4 + 2;
if (r < 6 / denom) {
// choose X
} else if (r < (6 + 4) / denom) {
// choose Y
} else {
// choose Z
}
what if I have n IPs how can I modify the code to deal with n IPs not a specific number of IPs?
Upvotes: 1
Views: 249
Reputation: 3006
Build an array with the cumulative weight of the ip's
Something like this
// C99 code
int pick_ip(int weights[], int nweights)
{
// note you can split this step out if you like (a good plan)
int cum_weights[nweights];
int tot_weight = 0;
for(int i=0; i < nweights; i++)
{
tot_weight += weights[i];
cum_weights[i] = tot_weight;
}
int t = (int)(tot_weight * rand() / (double)RAND_MAX);
if(cum_weights[0] > t) { return 0; }
// binary search for point that we picked
int v = -1;
int l = 0, u = nweights -1;
int m = u/2;
do { // binary search
if(cum_weights[m] > t) u = m;
else l = m;
m = (u + l)/2;
if(cum_weights[l+1] > t) {v=l+1; break;}
if(cum_weights[u-1] <= t) {v=u; break;}
} while(1);
}
Note: if you're doing lots of picking split out the building of the cumulative distribution array. Also if you want floating point weights you need to use a Khan sum to compute the cumulative weights (if you want code for doing that comment and I can add it to my example)
Upvotes: 0
Reputation: 3135
Here is an example of how to do this
and from that post:
int sum_of_weight = 0;
for(int i=0; i<num_choices; i++) {
sum_of_weight += choice_weight[i];
}
int rnd = random(sum_of_weight);
for(int i=0; i<num_choices; i++) {
if(rnd < choice_weight[i])
return i;
rnd -= choice_weight[i];
}
assert(!"should never get here");
Upvotes: 1