Hey guys, I'm new to programming and C, and I'm trying to write a program for a weighted dice, but I'm awful at math, and I can't figure out how to get it; it took my stupid self long enough to turn rand() into a number between 1 and 6. >.<
Can someone give me a nudge in the right direction?

I've got my

d = rand() % 6 + 1;

statement and I'm trying to weight the dice with an array of doubles that represent the probability of getting the number that corresponds to that array number.

For example:

double p[6] = { 1./6, 1./6, 1./6, 1./6, 1./6, 1./6 };

Would be a fair dice roll.

double p[6] = { 0.0, 0.75, 0.0, 0.0, 0.0, 0.25};

would be weighted with a 75% chance of getting a 2, and a 25% chance of getting a 6.

I feel really stupid that I can't figure this out. :(
Thanks so much!

I might think of it this way: For your second example you have 3/4 chance it will roll 2 and 1/4 chance of rolling a 6.
For this specific case, get a random number between 0 and 4(exclusive of 4). If you pick 0,1, or2, you've rolled 2 and if you pick 3 you've rolled 6 (or intersperse the value you want to pick to roll 6 among the lower values to make it potentially more "random"(a loaded word for your loaded dice)).
Have the user enter in the probabilities for the different numbers in ratios or else it will make more trouble for you.

Edited 6 Years Ago by jonsca: missing ')'

if you want to randomize based on weighted percentages, then you need to roll a percentage, not a value from 1-6.

think of something like "rand() % 100 + 1" , which gives a number from 1 to 100.

or for more resolution, float pctRoll = (float) (rand() % 1000) / 1000.0 this gives a value between 0.000 and 0.999 with 1000 roughly equal increments.

i got interested in this problem, and i wrote a program to perform various combinations of variouis numbers of weighted and fair dice, and print results as a normalized graph

here's the relevant snippet, stripped down to remove extra I/O, just to illustrate the logic behind testing the percentages, and sorting each roll into counting bins.

This supposes a simple case where a die has shaved faces for the 1 and 6 sides; this would give the 1 and 6 a higher chance of landing compared to the others. I declare the 1 and 6 sides each have a 30% chance, and the remaining sides have 10% each

float   p[7] = {0, 0.3, 0.1, 0.1, 0.1, 0.1, 0.3};  // pct chance each side
float   pct;   // the random "roll" expressed as decimal percent
int     diceBin[7] = {0,0,0,0,0,0,0}   // counts occurances for each side

// note arrays size 7 indexes 0-6, skipping use of "zeroth" element
// to make corresponding array info to die rolls 1-6 more intuitive.

for (i=0; i<NUM_ROLLS; i++)
(
   pct = (float)(rand() % 1024) / 1024;  // 0.000 to 0.999
      
   // put each roll into the proper bin
   if (pct < p[1])
      diceBin[1]++;
   else if (pct < (p[1] + p[2]))
      diceBin[2]++;
   else if (pct < (p[1] + p[2] + p[3]))
      diceBin[3]++;
   else if (pct < (p[1] + p[2] + p[3] + p[4]))
      diceBin[4]++;
   else if (pct < (p[1] + p[2] + p[3] + p[4] + p[5]))
      diceBin[5]++;
   else
      diceBin[6]++;
}

for (i = 1; i <= 6; i++)  // skips use of zeroth array element
   printf("Die %d : %5d / %d (%5.3f)\n", i, diceBin[i], NUM_ROLLS, (diceBin[i]/NUM_ROLLS));

.

Edited 6 Years Ago by jephthah: n/a

Note that generating a random number between 1 and N using rand() % N + 1 for small N is a poor solution because rand() often has very poor randomness in the low order bits of its return value.

read this

Rather than float pctRoll = (float) (rand() % 1000) / 1000.0; why not float pctRoll = (float)rand() / ((float)RAND_MAX + 1); which produces a similar result range but uses the entire return range (i.e. all bits) of rand().

Also the advice I here nowadays is that you should generally use double unless you have a specific comunicable reason to use float.

So double pctRoll = (double)rand() / ((double)RAND_MAX + 1);

Edited 6 Years Ago by Banfa: n/a

yes, good points.

i know about that particular rand method being not the best psuedo-randomizer. And i use the preferred method which you cited in my own programs.

but i figured he was just taught this particular "easy" way, and he already has enough new concepts to get a handle on before addressing more esoteric aspects of pseudo-random number generators than would be addressed Programming 101.

and i'm not sure why i used float. a voice in the back of my head was asking me the same question.

Edited 6 Years Ago by jephthah: n/a

Comments
Very good reasoning. KISS for new programmers. They don;t need the inner workings of perfection yet. RAND is good enough.
This article has been dead for over six months. Start a new discussion instead.