Running mean and variance

Almost done with my dice roll simulator which simulates a roll given a XdY user input.

There's only two problems: that my mean and standard deviation are all out of wack on option 2 (which performs a dice roll multiple times), and that my cin.fail() in option 2 is catching integers as well instead of just input with chars.

I'm sure that the first one is because I have the formula for mean and standard deviation written wrong, but I just couldn't seem to understand how to write it when I googled it.

Honestly no idea why the cin.fail() would catch on the other problem.

I appreciate the help

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
#include <ctime>
#include <sstream>
#include <string>
#include <iomanip>
#include <cmath>

using namespace std;

const int OPTION_SINGLE_ROLL = 1;
const int OPTION_MULTI_ROLL = 2;
const int OPTION_QUIT = 3;


int simulate_dice_roll (int x, int y) {    // simulates dice roll based on XdY input
    int result = 0;
    for (int i = 0; i < x; i++) {
        result += rand() % y + 1;
    }
    return result;
}

int extract_x (string dice_info_xdy) {   // extracts X value from XdY string input
    stringstream ss;
    ss << dice_info_xdy.substr(0, dice_info_xdy.find("d"));
    int x;
    ss >> x;
    return x;
}

int extract_y (string dice_info_xdy) {    // extracts Y value from XdY string input
    stringstream ss;
    ss << dice_info_xdy.substr(dice_info_xdy.find("d") + 1);
    int y;
    ss >> y;
    return y;
}

int validity_check (int x, int y, string dice_info_xdy){
    int invalid;
    if (x < 1 || y < 1 || dice_info_xdy.find("d") == -1) { // resets option if input is
        cout << "Invalid input." << endl;                  // invalid
        invalid = 1;
    }
    return invalid;
}

int main() {
    srand(time(NULL));
    bool return_to_root_menu;
    bool return_to_option_1;
    bool return_to_option_2;
    bool return_to_num_rolls;
    do {
        cout << "\t\t\t***ROOT MENU***\nPlease select one of the following options:\n1 - Simulate a single dice roll\n2 - Simulate multiple dice rolls\n3 - Quit the program\n";
        int option_choice;
        cin >> option_choice;
        cin.fail(); { // resets to root menu if a character or string is input instead of an int
            cin.clear();
            cin.ignore(1000, '\n');
        }
        if (option_choice == OPTION_SINGLE_ROLL){
            do {
                cout << "Please specify roll in XdY format: ";
                string dice_info_xdy;
                cin >> dice_info_xdy;
                int x, y;
                x = extract_x(dice_info_xdy);
                y = extract_y(dice_info_xdy);
                if (validity_check(x, y, dice_info_xdy) == 1) {
                    continue;
                }
                int result = simulate_dice_roll(x, y);
                cout << "Result: " << result << endl; // displays result of dice roll
                return_to_option_1 = true;
            } while (return_to_option_1 == false);
        }
        if (option_choice == OPTION_MULTI_ROLL) {
            do {
                cout << "Please specify roll in XdY format: ";
                string dice_info_xdy;
                cin >> dice_info_xdy;
                int x, y;
                x = extract_x(dice_info_xdy);
                y = extract_y(dice_info_xdy);
                if (validity_check(x, y, dice_info_xdy) == 1) {
                    continue;
                }
                do {
                    cout << "Please enter amount of times you would like to execute this roll: ";
                    int num_rolls;
                    cin >> num_rolls;
                    cin.fail(); { // resets to num rolls prompt if char is input
                        cin.clear();
                        cin.ignore(1000, '\n');
                        continue;
                    }
                    if (num_rolls < 1){ // resets to num rolls prompt if number less than 0 is input
                        continue;
                    }
                    if (num_rolls >= 1){
                        double total_result = 0;
                        double new_mean = 0;
                        double mean = 0;
                        double variance = 0;
                        for (int i = 0; i < num_rolls; i++){ // supposed to find running mean and standard
                            total_result = simulate_dice_roll(x, y);  //variation
                            mean = total_result / (i + 1);
                            new_mean += ((i + 1) - mean) / i;
                            variance += ((i + 1) - new_mean) * ((i + 1) - mean);
                        }
                        double std_deviation = sqrt(variance / (num_rolls - 1));
                        cout << "Min: " << x << "\nMax: " << x * y << "\nMean: " << new_mean << "\nStdDev: " << std_deviation << endl;
                    }
                    return_to_num_rolls = true; // ends num rolls loop
                } while (return_to_num_rolls == false);
                return_to_option_2 = true; // ends option 2 loop
            } while (return_to_option_2 == false);
            
        }
        if (option_choice == OPTION_QUIT) {
            cout << "Goodbye!";
            return_to_root_menu = true;
            continue;
        }
        return_to_root_menu = false; // resets to root menu when program is finished
        continue;
        return 0;
    } while (return_to_root_menu == false);
}
Last edited on
A couple things I notice right off the bat is that code below will always execute. I believe you want to clear/ignore/continue when cin.fail() returns true, but that means you have to wrap everything into an if statement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//lines 58-61
//runs cin.fail() and cin.clear() and cin.ignore() run regardless of what cin.fail() returns
cin.fail(); { // resets to root menu if a character or string is input instead of an int
            cin.clear();
            cin.ignore(1000, '\n');
        }

//lines 93-96
//runs cin.fail() and cin.clear(), cin.ignore(), continue run regardless of what cin.fail() returns
cin.fail(); { // resets to num rolls prompt if char is input
                        cin.clear();
                        cin.ignore(1000, '\n');
                        continue;
                    }
Awesome, thank you. Totally obvious now that I think about it.

I also seemed to have fixed the mean and stdDev.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <ctime>
#include <sstream>
#include <string>
#include <iomanip>
#include <cmath>

using namespace std;

const int OPTION_SINGLE_ROLL = 1;
const int OPTION_MULTI_ROLL = 2;
const int OPTION_QUIT = 3;


int simulate_dice_roll (int x, int y) {    // simulates dice roll based on XdY input
    int result = 0;
    for (int i = 0; i < x; i++) {
        result += rand() % y + 1;
    }
    return result;
}

int extract_x (string dice_info_xdy) {   // extracts X value from XdY string input
    stringstream ss;
    ss << dice_info_xdy.substr(0, dice_info_xdy.find("d"));
    int x;
    ss >> x;
    return x;
}

int extract_y (string dice_info_xdy) {    // extracts Y value from XdY string input
    stringstream ss;
    ss << dice_info_xdy.substr(dice_info_xdy.find("d") + 1);
    int y;
    ss >> y;
    return y;
}

int validity_check (int x, int y, string dice_info_xdy){
    int invalid;
    if (x < 1 || y < 1 || dice_info_xdy.find("d") == -1) { // resets option if input is
        cout << "Invalid input." << endl;                  // invalid
        invalid = 1;
    }
    return invalid;
}

int main() {
    srand(time(NULL));
    bool return_to_root_menu;
    bool return_to_option_1;
    bool return_to_option_2;
    bool return_to_num_rolls;
    do {
        cout << "\t\t\t***ROOT MENU***\nPlease select one of the following options:\n1 - Simulate a single dice roll\n2 - Simulate multiple dice rolls\n3 - Quit the program\n";
        int option_choice;
        cin >> option_choice;
        if (cin.fail() == true) { // resets to root menu if a character or string is input instead of an int
            cin.clear();
            cin.ignore(1000, '\n');
        }
        if (option_choice == OPTION_SINGLE_ROLL){
            do {
                cout << "Please specify roll in XdY format: ";
                string dice_info_xdy;
                cin >> dice_info_xdy;
                int x, y;
                x = extract_x(dice_info_xdy);
                y = extract_y(dice_info_xdy);
                if (validity_check(x, y, dice_info_xdy) == 1) {
                    continue;
                }
                int result = simulate_dice_roll(x, y);
                cout << "Result: " << result << endl; // displays result of dice roll
                return_to_option_1 = true;
            } while (return_to_option_1 == false);
        }
        if (option_choice == OPTION_MULTI_ROLL) {
            do {
                cout << "Please specify roll in XdY format: ";
                string dice_info_xdy;
                cin >> dice_info_xdy;
                int x, y;
                x = extract_x(dice_info_xdy);
                y = extract_y(dice_info_xdy);
                if (validity_check(x, y, dice_info_xdy) == 1) {
                    continue;
                }
                do {
                    cout << "Please enter amount of times you would like to execute this roll: ";
                    int num_rolls;
                    cin >> num_rolls;
                    if (cin.fail() == true) { // resets to num rolls prompt if char is input
                        cin.clear();
                        cin.ignore(1000, '\n');
                        continue;
                    }
                    if (num_rolls < 1){ // resets to num rolls prompt if number less than 0 is input
                        continue;
                    }
                    if (num_rolls >= 1){
                        double total_result = 0;
                        double mean = 0;
                        double variance = 0;
                        double std_deviation = 0;
                        double total_result1 = 0;
                        double array[num_rolls];
                        for (int i = 0; i < num_rolls; i++){ // supposed to find running mean and standard
                            array[i] = simulate_dice_roll(x, y);
                            total_result += array[i];
                        }
                        mean = total_result / num_rolls;
                        for (int i = 0; i < num_rolls; i++){ // supposed to find running mean and standard
                            total_result1 += pow((array[i] - mean), 2);
                        }
                        variance = total_result1 / num_rolls;
                        std_deviation = sqrt(variance);
                        cout << "Min: " << x << "\nMax: " << x * y << "\nMean: " << mean << "\nStdDev: " << std_deviation << endl;
                    }
                    return_to_num_rolls = true; // ends num rolls loop
                } while (return_to_num_rolls == false);
                return_to_option_2 = true; // ends option 2 loop
            } while (return_to_option_2 == false);
            
        }
        if (option_choice == OPTION_QUIT) {
            cout << "Goodbye!";
            return_to_root_menu = true;
            continue;
        }
        return_to_root_menu = false; // resets to root menu when program is finished
        continue;
        return 0;
    } while (return_to_root_menu == false);
}
Topic archived. No new replies allowed.