开发者

Can percentage probability be done with a switch and ranges in C?

开发者 https://www.devze.com 2023-03-30 22:58 出处:网络
I\'m currently using a random number and a series of if statements to assign a pointer to one of four lists using the following:

I'm currently using a random number and a series of if statements to assign a pointer to one of four lists using the following:

struct listinfo//struct holds head, tail and the number of entries for the n2l, norm, known and old lists
{
    struct vocab * head;
    int entries;
    struct vocab * tail;
};

...

int list_selector=0;
struct listinfo * currentlist = NULL;
//select a list at random, using the percentage probabilities in the if statements.
//FISH! Can this be done with a switch and ranges?
list_selector = (rand() % 100)+1;
if (list_selector<33) currentlist = &n2l;
if (list_selector>32&&list_selector<95) currentlist=&norm;
if (list_selector>94&&list_selector<100) cur开发者_运维技巧rentlist = &known;
if (list_selector==100) currentlist = &old;

I was just wondering if there's a neater way to do this using ranges in the switch as in this question. If so, an example would be great. Any additional tips would be much appreciated too.

Edit: Fixed! Was linking to wrong page instead of this.


I don't believe C supports ranges in switch statements. You could use an if-else construct to reduce comparisons:

if( x == 100 )
  ...
else if( x > 94 )
  ...

And your random number generator is not properly random: RAND_MAX is unlikely to be divisible by 100, so some numbers may be more common than others. Here is the accepted way to convert rand() to a properly random distribution from 1 to 100:

x = 1 + (int) ( 100.0 * ( rand() / ( RAND_MAX + 1.0 ) ) );


As noted before, C doesn't support ranges as switch case selectors. For a compact and efficient form, you could use C's ternary operator, eg:

r = (random() % 100)+1;
currentlist = r<33? &n2l : r<95? &norm : r<100? &known : &old;

or if you prefer could use nested if's, like:

currentlist = &n2l;
if (r>32) {
  currentlist = &norm;
  if (r>94) {
    currentlist = &known;
    if (r==100)
      currentlist = &old;
  }
}

Note, per man rand, "on older rand() implementations... the lower-order bits are much less random than the higher-order bits", so I prefer random() to rand(). Or go with the 100.0 * ( rand() / ( RAND_MAX + 1.0)) formula suggested by asc99c.


No, in this situation, using the less than, greater than, is much more efficient. For a switch, you'd have to outlay all of the different possibilities.

   case  1:     
         2:
         3:
         4:   
       /*write all the numbers out all the way up to 31, then for 32 */
        32: currentlist = &n2l;
   break;
   case  33:  
         34:
         35:
        /*write out all of these numbers until 94, then for 95 */
         95:  currentlist=&norm;
   break;         
   /*etc*/


If it's possible to change that (rand() % 100)+1 to provide fewer possible values, you'll have a much easier time with the solution.

If that's not possible, I'm trying to come up with a solution, but it seems like a tricksy problem at first glance (without listing every possible value).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号