471,873 Members | 1,661 Online

# Trouble calculating percentage in C++ dice program 41
I'm writing a program that will have to roll the dice A and dice B one million times, and calculate the percentage of times that the dies will be equal.

I'm having trouble to figure out how the percentage will work.

Here is my code:
Expand|Select|Wrap|Line Numbers
1.
2. #include <ctime>
3. #include <iostream>
4. using namespace std;
5.
6. const double roll = 1000000;
7.
8. int rolldie() //statement will give u 6
9. {
10. return (rand()%6+1);
11. }
12.
13. void Randomize()
14. {
15. srand( (unsigned)time( NULL ) ) ;
16. }
17.
18. int main()
19. {
20.     int diceA;
21.     int diceB;
22.     int totals;
23.     int i;
24.     cout << "Rolling dices one million times\n";
25.     Randomize();
26.
27.     for(i=0;i<roll;i++)
28.     {
29.         diceA = rolldie();
30.         diceB = rolldie();
31.         int    totals = diceA + diceB;
32.         totals++;
33.     }
34.
35.     if(diceA==diceB)
36.     {
37.         cout << "Doubles occurred" << totals / 1000000 << "percent of the time.";
38.     }
39.
40.     return 0;
41. }
42.

Doug
Aug 31 '07 #1
38 8908 sicarie
4,677 Expert Mod 4TB
Expand|Select|Wrap|Line Numbers
1.
2.     for(i=0;i<roll;i++)
3.     {
4.         diceA = rolldie();
5.         diceB = rolldie();
6.         int    totals = diceA + diceB;
7.         totals++;
8.     }
9.
10.
Okay, let's walk through this for two arbitrary dice rolls.

for (i = 0; 0 < 1000000; 0++)
diceA = 3 //made this up
diceB = 4 // made this up too
totals = 3 + 4 // so totals = 7
totals++ // so totals = 8

for (i =1; 1< 1000000; 1++)
diceA = 1
diceB = 5
totals = 1+5 // totals = 6
totals++ // totals = 7

Do you see the issue here? Not only does totals get wiped out every iteration through the loop, but you also don't get the right total amount because of the increment.

I think you want it to be

totals += diceA + diceB

and no totals++. ::Edit:: and you might want to move the 'int totals' out of the loop. It will probably be seen as a re-declaration of the variable each time, in which case you'll get undefined behavior, and who knows what you will get.

I also changed the title to be a bit more descriptive - draw a few more people in, if they have something to comment on.
Aug 31 '07 #2
JosAH
11,448 Expert 8TB
Expand|Select|Wrap|Line Numbers
1.     for(i=0;i<roll;i++)
2.     {
3.         diceA = rolldie();
4.         diceB = rolldie();
5.         int    totals = diceA + diceB;
6.         totals++;
7.     }
8.
Shouldn't you check *inside* that loop whether or not diceA equals diceB?
If they're equal you should increment a counter ('totals' mayhap?)

When the loop is finished you have rolled the dice 'roll' times and 'totals'
times they were equal.

kind regards,

Jos
Aug 31 '07 #3
d0ugg
41 Thank you so much,
That was very fast,

I will try that right now and let you guys know what happened.

Doug
Aug 31 '07 #4
sicarie
4,677 Expert Mod 4TB
Shouldn't you check *inside* that loop whether or not diceA equals diceB?
If they're equal you should increment a counter ('totals' mayhap?)

When the loop is finished you have rolled the dice 'roll' times and 'totals'
times they were equal.

kind regards,

Jos
Does the OP even need the check to see if they are the same? Why does the OP care if they are the same? They should be dealt with the same way, right?
Aug 31 '07 #5
kreagan
153 100+
Does the OP even need the check to see if they are the same? Why does the OP care if they are the same? They should be dealt with the same way, right?
The object of the assignment was to find the probability of doubles thrown. Your suggestion is for the average number thrown.
Aug 31 '07 #6
sicarie
4,677 Expert Mod 4TB
The object of the assignment was to find the probability of doubles thrown. Your suggestion is for the average number thrown.
Ah, good catch.
Aug 31 '07 #7
JosAH
11,448 Expert 8TB
Ah, good catch.
You should try a different brand of coffee ;-)

kind regards,

Jos (<--- Italian 'Illy' espresso)
Aug 31 '07 #8
sicarie
4,677 Expert Mod 4TB
You should try a different brand of coffee ;-)

kind regards,

Jos (<--- Italian 'Illy' espresso)
Yeah, I'm used to my wife's coffee. She's a nurse, and when people like that work 12 hour shifts, they tend to make it very very strong. Then I come to work and I'm drinking 3 cups and just starting to feel awake... (Hence the attempt at cutting back)
Aug 31 '07 #9
d0ugg
41 So,
I did what you told me

Expand|Select|Wrap|Line Numbers
1. for(i=0;i<roll;i++)
2.     {
3.         diceA = rolldie();
4.         diceB = rolldie();
5.         totals += diceA + diceB;
6.     }
7.
But not it seems that is running, but it's not printing anything.
And I also put the int totals out of the loop..

Any ideas why is not printing the percentage?

Thank you so much for the help,

Doug
Aug 31 '07 #10
JosAH
11,448 Expert 8TB
So,
I did what you told me

Expand|Select|Wrap|Line Numbers
1. for(i=0;i<roll;i++)
2.     {
3.         diceA = rolldie();
4.         diceB = rolldie();
5.         totals += diceA + diceB;
6.     }
7.
But not it seems that is running, but it's not printing anything.
And I also put the int totals out of the loop..

Any ideas why is not printing the percentage?

Thank you so much for the help,

Doug
Did you read my reply? You should check whether or not diceA and diceB are
equal; if so you should increment a counter. The way you do it now you simply
add both scores to the running total; that is wrong.

kind regards,

Jos
Aug 31 '07 #11
kreagan
153 100+
So,
I did what you told me

Expand|Select|Wrap|Line Numbers
1. for(i=0;i<roll;i++)
2.     {
3.         diceA = rolldie();
4.         diceB = rolldie();
5.         totals += diceA + diceB;
6.     }
7.
But not it seems that is running, but it's not printing anything.
And I also put the int totals out of the loop..

Any ideas why is not printing the percentage?

Thank you so much for the help,

Doug
Did you read anyone's posts except sicarie? If you did, you should have known that his suggestion was solving another problem. Also, your if statement is in the wrong place. You will only print out if diceA and diceB are equal on the last iteration.
Aug 31 '07 #12
d0ugg
41 Hello,

Sorry for been very stupid.

Well, I tried to include it on the loop but still doesn't work. It compiles but when I run, it really doesn't show the right answer.
Here is my "fixed" code.

Expand|Select|Wrap|Line Numbers
1. #include <ctime>
2. #include <iostream>
3. using namespace std;
4.
5. const double roll = 1000000;
6. int totals;
7.
8. int rolldie() //statement will give u 6
9. {
10. return (rand()%6+1);
11. }
12.
13. void Randomize()
14. {
15. srand( (unsigned)time( NULL ) ) ;
16. }
17.
18. int main()
19. {
20.     int diceA;
21.     int diceB;
22.     int i;
23.     cout << "Rolling dices one million times\n";
24.     Randomize();
25.
26.     for(i=0;i<roll;i++)
27.     {
28.         diceA = rolldie();
29.         diceB = rolldie();
30.
31.         for(diceA=diceB;totals++;)
32.         {
33.             cout << "Doubles occurred" << totals / 1000000 << "percent of the time.";
34.         }
35.     }
36.
37.     return 0;
38. }
39.
Thank you for the help,

DOug
Aug 31 '07 #13
sicarie
4,677 Expert Mod 4TB
Expand|Select|Wrap|Line Numbers
1.     for(i=0;i<roll;i++)
2.     {
3.         diceA = rolldie();
4.         diceB = rolldie();
5.
6.         for(diceA=diceB;totals++;)
7.         {
8.             cout << "Doubles occurred" << totals / 1000000 << "percent of the time.";
9.         }
10.     }
11.
Okay, why did you decide to put the 'for(diceA=diceB;totals++;) in the for loop?

That's the thing you want to happen one time, and if it is in the for loop, it will happen every time. It would seem to me you want that outside the for loop. (Though you still want to have _something_ in there to increment totals if a is equal to b.)

Also, the diceA=diceB means you are going to assign the value of B to A. You want the '==' double equals, which is the conditional. If diceA==diceB, then do whatever - you don't need a for loop, in fact, I don't think you need anything there, just the print statement.
Aug 31 '07 #14
JosAH
11,448 Expert 8TB
Sorry for been very stupid.
Nobody thinks your stupid; you just don't 'speak' C or C++ yet so lets forget
about that for a second. I give you a piece of paper and a pencil. I'm going
to roll two dice 'n' times. After every roll I show your their score.

What do you have to do after I rolled those dice? Be quick because I'm going
to roll them again. Just use simple English please.

kind regards,

Jos
Aug 31 '07 #15
d0ugg
41 Oh okay,
But my now my question is..
I don't know how to add in the for loop if (diceA == diceB = totals) and than increment.. Is there anywhere that I can look for that?
Aug 31 '07 #16
d0ugg
41 Oh and by the way,

After I roll the dices I need to calculate the percentage of times that the dices will have the same value, when the dices will equal to 7 and also when the dices will each have values of 1.
Aug 31 '07 #17
Ganon11
3,652 Expert 2GB
As Jos suggested, think about how you might tackle this problem without a computer. A fundamental idea about programming is an algorithm - a series of steps you must take in order to solve the problem. You can think of a correct algorithm without touching a computer. Once you have this algorithm, it is easy to translate this into code.

Suppose I want to write a program to calculate the average score on some test I give. I have all the student's results; now what do I do? Well, I would add up all the student's results and divide by the number of students, giving me the average score per student. My algorithm would be:

1) Retrieve the scores from my students
2) Total these scores
3) Divide this total by the total number of students

From this algorithm, it would be simple to write a program.

What you need to do is to spend some time away from your program. Stop thinking in code for a bit, and instead focus on an algorithm to determine the percentage of doubles. Once you have figured out how to do this without a computer, then and only then focus on writing code for that algorithm.

(By the way, as Jos said, no one thinks you're stupid. There's a huge difference between 'stupid' and 'inexperienced with programming. I can almost guarantee you that most, if not all, of the moderators and experts here were, at one point, as confused as you. What tells me that you are, in fact, not stupid, is that you have so far refused to stop trying to solve this problem, and that you were smart enough to ask for help when you needed it. So, from one rookie to another (because I don't have much experience either ;) ), don't feel bad when you ask for help.)
Aug 31 '07 #18
JosAH
11,448 Expert 8TB
Oh and by the way,

After I roll the dices I need to calculate the percentage of times that the dices will have the same value, when the dices will equal to 7 and also when the dices will each have values of 1.
You're way too fast for me; lets go slowly: I present you an arbitrary pair of dice;
what do you do? hint: you do have a counter which you can increment. What
do you do if I present you the pair 5,4? Do you increment that counter if you
want that counter to represent the number of equal pairs I've shown you?
I guess not. You do increment that counter when I present you a pair, say: 3, 3.

So basically this is what's happening:

Expand|Select|Wrap|Line Numbers
1. me: I show you a pair x, y
2.    you: you do something that makes sense.
3.
Your turn: what makes sense here? Note that I sneakily indented that 'pseudo'
code because I'm gonna show you a lot of pair of dice and you have to make
a sensible decision over and over again.

kind regards,

Jos
Aug 31 '07 #19
kreagan
153 100+
Glad to see you are still trying this problem. Like many people already said, we all had to start at the beginning. Along with the suggestions on writing psuedo code without thinking about code (which is a good practice even for experienced programmers), place couts everywhere expecially for loops and if statements. If you have a debugger, use that too.

Expand|Select|Wrap|Line Numbers
1.     for(i=0;i<roll;i++)
2.     {
3.                 cout << "Entering For Loop. i =" << i;  //added
4.         diceA = rolldie();
5.                 cout << "DiceA is" << diceA;   //added debug line
6.         diceB = rolldie();
7.                 cout <<"DiceB is" << diceB;   //added debug line
8.         int totals = diceA + diceB;
9.                 cout <<"totals is when dice are added together" << totals;
10.         totals++;
11.                 cout <<"totals is after increment" << totals;
12.     }
This can allow you to see the flow of your code. Also, it will point out parts that you expected to behaive differently. When I started, I used them heavily and could see the logic flow of the program before I was confortable with reading code.

Good luck
Aug 31 '07 #20
d0ugg
41 Thanks for all the support guys, I just got home now and I going to work some more tonight on the code..

So basically I already understood what I have to do.. Here is my way..

First declare Dice A and also Dice B, than I want to roll Dice A and also Dice B one million times. After that I will see how many times Dice A equals to Dice B, but unfortunately I don't know how to do that in the for loop yet, I tried a couple things but still get some errors..

Thanks,

~doug
Sep 1 '07 #21
Ganon11
3,652 Expert 2GB
Thanks for all the support guys, I just got home now and I going to work some more tonight on the code..

So basically I already understood what I have to do.. Here is my way..

First declare Dice A and also Dice B, than I want to roll Dice A and also Dice B one million times. After that I will see how many times Dice A equals to Dice B, but unfortunately I don't know how to do that in the for loop yet, I tried a couple things but still get some errors..

Thanks,

~doug
You're on the right track. But you have the order wrong. Once you have rolled DiceA and DiceB 1,000,000 times, how are you going to check if they were ever equal? Once you re-roll a die, you've lost its previous number. You need to check if DiceA and DiceB are equal right after they've been rolled - inside the loop with their rolls.
Sep 1 '07 #22
d0ugg
41 Good point, thank you for the quick answer..
So right now my loop code is just like that

Expand|Select|Wrap|Line Numbers
1. for(i=0;i<roll;i++)
2.           {
3.               diceA = rolldie();
4.                       cout << "DiceA is\n" << diceA;   //added debug line
5.               diceB = rolldie();
6.                       cout <<"DiceB is\n" << diceB;   //added debug line
7.               //diceA == diceB;
8.                      // cout <<"totals is when dice are added together" << totals;
9.               //totals++;
10.               //       cout <<"totals is after increment" << totals;
11.           }
12.
*Where I put // its because I don't know the syntax, I'm not sure yet how I will check diceA == DiceB.

*
I just had an idea, I decided to create a check function that will see if diceA and diceB is equal..

So now, I have also this in my code:

Expand|Select|Wrap|Line Numbers
1. int check()
2. {
3.     while(diceA==diceB)
4.     return 0;
5. }
6.
Does that loop work for this kind of situation?

Thanks,

~doug
Sep 1 '07 #23
Studlyami
464 Expert 256MB
Your close. Rather than doing while DiceA==DiceB use an if statment during the for loop. You don't want to use while (DiceA==DiceB) because while is a loop and the loop will stop when the conditions are not met (I.E. DiceA is not equal to DiceB). We are not interested in how many time in a row DiceA == DiceB. We just want how many times out of a million rolls were they equal.

Below is the basic flow your looking for.

Expand|Select|Wrap|Line Numbers
1. for(int i = 0; i< TotalNumberOfRolls; i++)
2. {
3.    DiceA = Roll; //value 1-6
4.    DiceB = Roll; //value 1-6
5.     if(DiceA==DiceB)
6.    {
7.         //The Two dice are the same so incriment counter
8.    }
9. }
10.
11. cout<<"The dice were equal" << counter<<" Times";
12.
Sep 1 '07 #24
kreagan
153 100+
Good point, thank you for the quick answer..
So right now my loop code is just like that

So now, I have also this in my code:

Expand|Select|Wrap|Line Numbers
1. int check()
2. {
3.     while(diceA==diceB)
4.     return 0;
5. }
6.
Does that loop work for this kind of situation?

Thanks,

~doug
Great idea on creating the function. As for what is in the function, the loop won't work What is happening is, the while loop checks if the statement is true. If it is true, a zero will be returned. If it isn't true, nothing will be return (that's bad). Because of the return statement, you only run the while loop once. But if you remove the return statement, the program run the while loop forever or never. (Try placing the return 0 with cout << "I'm in the while loop" and you will see what I mean.) But there is another tool you can use that will only check it once. People have been hinting towards it. An IF statement.

When looking at an if statement, read it as

if ( something is true ) {
do X
}
else if ( something else is true ) { // if above statement is not true
do Y
}
else // if nothing above is true
do Z
}

where X, Y, and Z are just different procedures. For example returning 0 or rolling a dice. Whatever you want to put into it.
Sep 1 '07 #25
d0ugg
41 Hello Everyone,

Thanks for all the support one more time..
So right now my loop looks like this:

Expand|Select|Wrap|Line Numbers
1. for(int i=0; i<roll; i++)
2. {
3.     diceA = rolldie(); //value 1-6
4.     diceB = rolldie(); //value 1-6
5.         if(diceA==diceB)
6.         {
7.             i++;
8.         }
9. }
10.         cout<<"The dice were equal " << i <<" Times\n";
11.         return 0;
12.
- The compiler does not reject my code, but it is a little bit weird because out of one million random rolls, it does not find any time that the Dice A = Dice B..

~doug
Sep 2 '07 #26
Studlyami
464 Expert 256MB
a couple of problems there.
1.) depending on your compiler when you do the cout<<"the dice... <<i<<
'i' was created in the for loop and on some compliers might lose i at the end of the loop (VS 2005 won't even let it compile).

2.) even if 'i' retained its value you are going to have i = 1,000,000 because the loop will stop when i >= 1,000,000. At the end of every loop you increase it by one. You also increase 'i' if the dice rolls are the same. You need 2 seperate counters. one to count the rolls the other to count the doubles.

fix those and it works like a charm.
Sep 2 '07 #27
d0ugg
41 Okay..

Finally I got one step done..
I got the loop working correctly..
Here is the code

Expand|Select|Wrap|Line Numbers
1. for(int total=1; total<=1000000; total++)
2. {
3.     diceA = rolldie(); //value 1-6
4.     diceB = rolldie(); //value 1-6
5.         if(diceA==diceB)
6.         {
7.             cout << setw(7) << "The dice were equal: " << total << endl;
8.         }
9. }
10.
I just realize that i don't need to increment anything, because it will already run one million times and see when they are equal..
But now my problem is..

Calculate the percentage of times that they are equal..
Sep 2 '07 #28
JosAH
11,448 Expert 8TB
I just realize that i don't need to increment anything, because it will already run one million times and see when they are equal..
But now my problem is..

Calculate the percentage of times that they are equal..
Well, you've realized it wrong then ;-) Instead of telling the world everytime the
dice were equal you should increment a counter; that counter indicates the number
of equal rolls when the loop has finished; now you have two numbers:

1) 'roll' the number of rolls in total (here: 1,000,000)
2) 'counter' the number of rolls that were equal.

Now you do the simple math.

kind regards,

Jos
Sep 2 '07 #29
d0ugg
41 I started the code again..

Here is my code now

Expand|Select|Wrap|Line Numbers
1. #include <iostream>
2. #include <ctime>
3.
4. using namespace std;
5.
6. void randomize();
7. int verify_1();
8. void calculate_1();
9. int rolldie();
10.
11. void randomize(int *diceA, int *diceB)
12. {
13. srand((unsigned)+time(NULL));
14. *diceA = rand() %6+1;
15. srand((unsigned)+time(NULL));
16. *diceB = rand() %6+1;
17. }
18.
19. int verify_1(int diceA, int diceB)
20. {
21. int roll;
22. if(diceA==diceB)
23. roll++;
24. return roll;
25. }
26.
27.
28. void calculate_1(float *doubles)
29. {
30. *doubles = *doubles/1000000;
31. }
32.
33.
34. int main()
35. {
36. int diceA;
37. int diceB;
38. float roll;
39. float doubles=0;
40.
41. cout << "One million dice rolls";
42. for (roll=0; roll<1000000; roll++)
43. {
44. randomize(&diceA, &diceB);
45. doubles=verify_1(diceA, diceB);
46. calculate_1(&doubles);
47. cout << doubles;
48. return 0;
49.
50. }
51. }
52.
53.

However when I run it shows me the percentage 0.. I don't know where I add something wrong..

The compiler does not give me any error, but gives me 2 warnings..

1 warning '=' : conversion from 'int' to 'float', possible loss of data
2 warning = uninitialized local variable 'roll' used

Thanks,

~doug
Sep 2 '07 #30
Studlyami
464 Expert 256MB
Expand|Select|Wrap|Line Numbers
1. void randomize(int *diceA, int *diceB)
2. {
3. srand((unsigned)+time(NULL));
4. *diceA = rand() %6+1;
5. srand((unsigned)+time(NULL));
6. *diceB = rand() %6+1;
7. }
8.
you only need to do the srand once.

Expand|Select|Wrap|Line Numbers
1. int verify_1(int diceA, int diceB)
2. {
3. int roll;
4. if(diceA==diceB)
5. roll++;
6. return roll;
7. }
8.
here you initiate roll. every time you call this function roll gets reset. You are also not initializing roll to 0. int roll = 0; if not when you do roll++ you will get a messed up value.
Sep 2 '07 #31
d0ugg
41 Okay, thanks.
It looks like this now

Expand|Select|Wrap|Line Numbers
1. int verify_1(int diceA, int diceB)
2. {
3.     int roll=0;
4.     if(diceA==diceB)
5.     roll++;
6.     return roll;
7. }
8.
But how do I initialize it from the different number everytime?
Example(Roll=1,roll=2,roll=3.. etc)

~doug
Sep 2 '07 #32
Studlyami
464 Expert 256MB
sorry i didn't make myself clear. You only want to initialize roll once, but what is happening is every time you call that function it will initialize roll. you want a function like that you will need to pass in roll by reference.

Expand|Select|Wrap|Line Numbers
1. void verify_1(int diceA, int diceB, int *roll)
2. {
3.     if(diceA==diceB)
4.     *roll++;
5. }
6.
then in main before you do the for loop initialize roll to zero

int roll = 0;
Sep 2 '07 #33
d0ugg
41 Do you mean

Expand|Select|Wrap|Line Numbers
1. int verify_1(int diceA, int diceB, float *roll)
2. {
3.     if(diceA==diceB)
4.     *roll++;
5. return *roll;
6. }
7.
??
Because the compiler say that it has to return a value...

~doug
Sep 2 '07 #34
Studlyami
464 Expert 256MB
I played with your code for a bit and it was giving me problems so i decided to make it simple and put it in main. Here is the basic program, then you can try to put it into separate functions as you see fit.

Expand|Select|Wrap|Line Numbers
1. #include <iostream>
2. #include <ctime>
3. using namespace std;
4.
5. int main()
6. {
7.     srand( (unsigned)time( NULL ) ) ;
8.
9.     int diceA = 0; //will get dicea value
10.     int diceB = 0; // will get diceb value
11.     int DoubleTotal = 0; //keeps track each time we get a dobule
12.
13.     for(int i = 0; i<1000000; i++)
14.     {
15.         diceA = rand()%5 +1; //value 1-6
16.         diceB = rand()%5 +1; //value 1-6
17.         if(diceA==diceB)
18.         {
19.             DoubleTotal++;
20.         }
21.     }
22.     cout<<"The dice were equal " << DoubleTotal <<" Times\n";
23.
24.     return 0;
25. }
26.
Sep 2 '07 #35
d0ugg
41 Thanks for the support,
but it is suppose to give the percentage of times that it happened.. But anyways, thanks!
Sep 2 '07 #36
Studlyami
464 Expert 256MB
Your Welcome. The percentage is just a simple math element at the end. You were really close at one point, you only needed to change like 2 lines, but then you split them up into functions and got confused again. I hope you can follow the logic and now that you have a working main try to split it up into the functions that you wanted.
Sep 2 '07 #37
JosAH
11,448 Expert 8TB
Thanks for the support,
but it is suppose to give the percentage of times that it happened.. But anyways, thanks!
Sure, that's step 2; do you get an acceptible number for the number of times the
dice rolls were equal? e.g. total = 1,000,000, equals = 166,667.

kind regards,

Jos
Sep 2 '07 #38
d0ugg
41 Hello!

Thank you so much for the help everyone..

Have a good Sunday! ;)

~doug
Sep 2 '07 #39

 5 posts views Thread by eliana82 | last post: by 4 posts views Thread by clairelee0322 | last post: by 1 post views Thread by clairelee0322 | last post: by 5 posts views Thread by Aswanth | last post: by 4 posts views Thread by zoeb | last post: by 4 posts views Thread by lee123 | last post: by 1 post views Thread by zufie | last post: by 4 posts views Thread by sureshl | last post: by 9 posts views Thread by Steel546 | last post: by reply views Thread by antdb | last post: by reply views Thread by YellowAndGreen | last post: by reply views Thread by isladogs | last post: by reply views Thread by beacampos | last post: by reply views Thread by isladogs | last post: by 1 post views Thread by Sullster47 | last post: by 1 post views Thread by anoble1 | last post: by reply views Thread by beacampos | last post: by reply views Thread by jesuscortes0 | last post: by