rand issues

I am having a bit of trouble with some code I have recently written. It runs without errors right now, but it needs to do a few more things that i have yet to figure out.

The program asks the user for the answers to 4 mathematical questions whose inputs are all between 10 and 99. one problem is addition, one subtraction, one multiplication, and one divison.

The program displays a message telling the user if they answered incorrectly, and gives them another shot at the same problem.

The program is supposed to display one of the 3 random congratulatory message if the user gets the answer correct. **I am stumped on this one so far.**
The messages are:

“Nice Job!"
“Congratulations! Your answer is correct.”
“Yes! You are right!”

So far I have it set to just display "Nice!"

Here it is so far:

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
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <iomanip>

using namespace std;

int main()
{
srand(time(NULL));

int a = rand()%(99-10+1) + 10;
int b = rand()%(99-10+1) + 10;
int c = rand()%(99-10+1) + 10;
int d = rand()%(99-10+1) + 10;
double e = rand()%(99-10+1) + 10;
double f = rand()%(99-10+1) + 10;
double g = rand()%(99-10+1) + 10;
double h = rand()%(99-10+1) + 10;

double value_1, value_2, value_3, value_4;

cout<< "This program will test your arithmetic skills.\n \n";

cout<<"  "<<a<<"+"<<b<< " = ";
cin>>value_1;

while (value_1 != (a+b))
    {
        cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
        cout<< "  "<<a<<"+"<<b<< " = ";
        cin>> value_1;
    }

if (value_1 = (a+b))
    {
        cout<< "\n Nice!\n\n";
    }

cout<<"  "<<c<<"-"<<d<< " = ";
cin>>value_2;

while (value_2 != (c-d))
    {
        cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
        cout<< "  "<<c<<"-"<<d<< " = ";
        cin>> value_2;
    }

if (value_2 = (c-d))
    {
        cout<< "\n Nice!\n\n";
    }

cout<<"  "<<e<<"*"<<f<< " = ";
cin>>value_3;

while (value_3 != (e*f))
    {
        cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
        cout<< "  "<<e<<"*"<<f<< " = ";
        cin>> value_3;
    }

if (value_3 = (e*f))
    {
        cout<< "\n Nice!\n\n";
    }

cout<<"  "<<g<<"/"<<h<< " = ";
cin>>value_4;

while (value_4 <= (g/h)-.009 || value_4 >= (g/h)+.009)
    {
        cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
        cout<< "  "<<g<<"/"<<h<< " = ";
        cin>> value_4;
    }

if (value_4 >= (g/h)-.009 && value_4 <= (g/h)+.009)
    {
        cout<< "\n Nice!\n\n";
    }

    return 0;
}


I am having some issues with the division problem as well. The users answer is supposed to be okay as long as the answer is correct out to 2 decimal places.

The way I have the program now, issues could arise...

take for instance a problem 56/47 whose answer is approx. 1.1914894

With the code I have, the answer 1.185 would be considered correct because it lies within -.009 of the actual answer. This however should not be the case, for the users answer should be accurate to 2 decimal places.
Last edited on
You are confusing = (assignment) with == (comparison) several places in this code.

You also should not directly compare floating point values. As strange as it may sound...

1
2
3
4
5
6
7
8
double problem = 0.5 * 2.0;
double solution = 1.0;

if(problem == solution)
{
  // This code block might not execute!
  //  floating point numbers are not exact, so direct comparison with == or != is unreliable!
}



As for your questions:

The program is supposed to display one of the 3 random congratulatory message if the user gets the answer correct. **I am stumped on this one so far.**


What you want it a lookup table. Put the possible responses in an array, and generate a random index. That index selects which entry in the array you want to use for your message.

With the code I have, the answer 1.185 would be considered correct because it lies within -.009 of the actual answer. This however should not be the case, for the users answer should be accurate to 2 decimal places.


The easiest way (IMO) to compare numbers up to a certain decimal point is to remove the decimal from the equation entirely. This is easily accomplished by casting the number to an integer (doing so drops the decimal).

If you want to retain 2 decimal places, you can just move them to the other side of the decimal. for example:

1
2
3
4
5
6
7
8
9
10
11
double a = 0.123;
double b = 0.127;

int aint = (int)(a * 100);  // *100 to retain 2 decimal places
                      // cast to int to drop the remaining decimal places
int bint = (int)(b * 100);

if(aint == bint)
{
  // correct!
}
Last edited on
For the printing out of a random message, put the strings into a vector and use random_shuffle. Then take to first element.
http://www.cplusplus.com/reference/algorithm/random_shuffle

For the division, take what the real answer is and what the user entered and multiply by 100 and cast to an integer. This will convert your decimal to an integer with 2 decimal places of accuracy.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int userVal(static_cast<int>(100.0*value_4));
int progVal(static_cast<int>(100.0*(g/h)));
cout << "UserVal: " << userVal << " progVal: " << progVal << endl;

while (userVal != progVal)
{
   cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
   cout<< "  "<<g<<"/"<<h<< " = ";
   cin>> value_4;
   userVal=static_cast<int>(100.0*value_4);
}

if (userVal == progVal)
{
   cout<< "\n Nice!\n\n";
}


Take a look at at but check it I think I saw some one case where there might have been a round off issue.

Edit: Too slow by 5 minutes
Last edited on
random_shuffle is a bit excessive. A fixed lookup table is much simpler, IMO

1
2
3
static const char* answers[] = {"great!", "fantastic!", "you're awesome!"};

cout << answers[rand() % 3];
It's always nice to learn something new. I didn't know about it until I read a response to a question here. Plus at some point maybe he does a project with dealing cards.
I found the issue that I referred to above about round off. If in your divide you had 69/50 the answer would be 1.38 exactly. But the computer can't represent the value of 1.38 exactly when read in from cin, it gets 1.3799999999999. So, when you multiply by 100 you get 137. Internal the computer does know that 69/50*100 is 138, so you would put in 1.38 and the loop would say your wrong.
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
#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
   double g(69), h(50),value_4;

   cout<<"  "<<g<<"/"<<h<< " = ";
   cin>>value_4;
   int userVal(static_cast<int>(100.0*value_4));
   int progVal(static_cast<int>(100.0*(g/h)));
   cout << "UserVal: " << userVal << " progVal: " << progVal << endl;

   while (userVal != progVal) {
        cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
        cout<< "  "<<g<<"/"<<h<< " = ";
        cin>> value_4;
        userVal=static_cast<int>(100.0*value_4);
        cout << "UserVal: " << userVal << " progVal: " << progVal << endl;
   }

   if (userVal == progVal) {
        cout<< "\n Nice!\n\n";
   }

    return 0;
}

The only way to exit is to enter 1.389:

./a.out
  69/50 = 1.38
UserVal: 137 progVal: 138
Sorry, wrong answer. Please try to enter the correct answer again. 

  69/50 = 1.389
UserVal: 138 progVal: 138

 Nice!

Was thinking of using ceil but I think there is a issue with that as well. I haven't tested enough yet
Thanks for your responses histrungalot and Disch.

I have edited my code at bit using your explanations, however I am not sure I am completely comfortable with this bit of code:

1
2
3
static const char* answers[] = {ans1,ans2,ans3};

cout << answers[rand() % 3]


Can someone try to help explain it a bit further? especially the role of the modulus in that specific example.

Also, thats an interesting find histrungalot, although I am having a bit of trouble following your code given my limited experience with C++.

So, at this point I have left the + or - .009 due to the issue you mentioned above, however any additional solutions or picking apart of my code would be appreciated.

Here it is now:
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
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <iomanip>

using namespace std;

int main()
{
    srand(time(NULL));

    int a = rand()%(99-10+1) + 10;
    int b = rand()%(99-10+1) + 10;
    int c = rand()%(99-10+1) + 10;
    int d = rand()%(99-10+1) + 10;
    int e = rand()%(99-10+1) + 10;
    int f = rand()%(99-10+1) + 10;
    double g = rand()%(99-10+1) + 10;
    double h = rand()%(99-10+1) + 10;

    double value_1, value_2, value_3, value_4;

    static const char* answers[] = {"\nNice Job!\n\n" , "\nCongratulations! Your answer is correct.\n\n", "\nYes! You are right!\n\n"};

    cout<< "This program will test your arithmetic skills.\n \n";

    cout<<"  "<<a<<"+"<<b<< " = ";
    cin>>value_1;

        while (value_1 != (a+b))
        {
            cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
            cout<< "  "<<a<<"+"<<b<< " = ";
            cin>> value_1;
        }

        if (value_1 == (a+b))
        {
            cout << answers[rand() % 3];
        }

    cout<<"  "<<c<<"-"<<d<< " = ";
    cin>>value_2;

        while (value_2 != (c-d))
        {
            cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
            cout<< "  "<<c<<"-"<<d<< " = ";
            cin>> value_2;
        }

        if (value_2 == (c-d))
        {
        cout << answers[rand() % 3];
        }

    cout<<"  "<<e<<"*"<<f<< " = ";
    cin>>value_3;

        while (value_3 != (e*f))
        {
            cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
            cout<< "  "<<e<<"*"<<f<< " = ";
            cin>> value_3;
        }

        if (value_3 == (e*f))
        {
            cout << answers[rand() % 3];
        }

    cout<<"  "<<g<<"/"<<h<< " = ";
    cin>>value_4;

        while (value_4 <= (g/h)-.009 || value_4 >= (g/h)+.009)
        {
            cout<< "Sorry, wrong answer. Please try to enter the correct answer again. \n\n";
            cout<< "  "<<g<<"/"<<h<< " = ";
            cin>> value_4;
        }

        if (value_4 >= (g/h)-.009 && value_4 <= (g/h)+.009)
        {
            cout << answers[rand() % 3];
        }

    return 0;
}


Can someone try to help explain it a bit further? especially the role of the modulus in that specific example.


Using modulus with rand is a common way to get random numbers within a specific range.

rand() % X effectively gives you a random number between [0..X). So rand() % 3 will give us 0, 1, or 2.

We can then use that random number an an index for our lookup table, which gives us one of the 3 strings.
Last edited on
Topic archived. No new replies allowed.