Thread: Random operator for simple maths program

  1. #1
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128

    Random operator for simple maths program

    Hi everyone,

    I've written my daily small program, and this one is a maths quiz. Well, not much of a quiz just yet. Here's the program:

    Code:
    #include <iostream>
    
    int main()
    {
        int numberA;
        int numberB;
        int userGuess;
        char anotherGo;
        
            do
            {
                std::cout << "Please enter a number: ";
                std::cin >> numberA;
                std::cout << "Please enter another number: ";
                std::cin >> numberB;
                
                std::cout << "What is " << numberA << " x " << numberB << "? ";
                int answer = numberA * numberB;
                std::cin >> userGuess;
                std::cout << std::endl;
                
                if (userGuess != answer)
                {
                    std::cout << "Sorry, that's the wrong answer.";
                }
                else
                {
                    std::cout << "Correct!";
                }
                
                std::cout << "\nDo you want another go? 1 for yes, 0 for no: ";
                std::cin >> anotherGo;
                std::cout << std::endl;
                
                if (anotherGo == '0')
                {
                    anotherGo = '0';
                }
            
            } while (anotherGo == '1');
        
        std::cout << "Exit program";
    
    }
    What I am trying to do is two things:

    1) Use a random operator for the expression, so if the user enters 3 and 3, the question would be either 3 x 3, 3 + 3, 3 - 3 or 3 / 3 (of course with a corresponding answer).

    I am thinking to either have the following lines physically written in the program:

    Code:
    std::cout << "What is " << numberA << " x " << numberB << "? ";
    std::cout << "What is " << numberA << " + " << numberB << "? ";
    std::cout << "What is " << numberA << " - " << numberB << "? ";
    std::cout << "What is " << numberA << " / " << numberB << "? ";
    And of course, an update to the logic in:

    Code:
    if (userGuess != (numberA * numberB))
    Or, I thought maybe there is a way to just have one line:

    Code:
    std::cout << "What is " << numberA << " x " << numberB << "? ";
    And somehow only change the " x " bit randomly. Kind of like how I would use a token in Drupal (it's the only example I can think of).

    The logic in my head goes like this:

    1) User inputs number
    2) Number is assigned to variable int numberA
    3) User inputs number
    4) Number is assigned to variable int numberB
    5) The answer is stored in variable int answer
    6) A question is generated (??) which asks for numberA (+,-,* or /) numberB (i.e. what is int answer)
    7) User inputs answer
    8) int answer is compared to int userGuess
    9) If wrong, print, if correct, print
    10) Another go?

    I'm just a bit (understatement) lost on how to go about this and not sure if what I've learned so far will allow me to do this. You can see so far all it does is multiply the 2 numbers. Any pointers would be very much appreciated. Thanks.
    Last edited by samwillc; 04-08-2013 at 02:38 PM.

  2. #2
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128
    Can I quickly add, maybe this will clarify it a bit what I am trying to do:

    Code:
    #include <iostream>
    
    float divide (float x, float y); //function to divide numbers
    int multiply (int x, int y); //function to multiply numbers
    int add (int x, int y); //function to add numbers
    int subtract (int x, int y); //function to subtract numbers
    
    int main()
    {
        int x;
        int y;
        int userGuess;
        char anotherGo = '1';
        
            do
            {
                std::cout << "Please enter a number: ";
                std::cin >> x;
                std::cout << "Please enter another number: ";
                std::cin >> y;
                
                std::cout << "What is " << x << " x " << y << "? "; // this line would need to change depending on what the operator is
                int answer = multiply(x, y); // can this line be randomized somehow to use a different function each time??
                std::cin >> userGuess;
                std::cout << std::endl;
                
                if (userGuess != answer)
                {
                    std::cout << "Sorry, that's the wrong answer.";
                }
                else
                {
                    std::cout << "Correct!";
                }
                
                std::cout << "\nDo you want another go? 1 for yes, 0 for no: ";
                std::cin >> anotherGo;
                std::cout << std::endl;
                
                if (anotherGo == '0')
                {
                    anotherGo = '0';
                }
            
            } while (anotherGo == '1');
        
        std::cout << "Exit program";
    
    }
    
    float divide (float x, float y) //function to divide numbers
    {
        return x / y;
    }
    
    int multiply (int x, int y) //function to multiply numbers
    {
        return x * y;
    }
    
    int add (int x, int y) //function to add numbers
    {
        return x + y;
    }
    
    int subtract (int x, int y) //function to subtract numbers
    {
        return x - y;
    }

  3. #3
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128
    I thought I had worked it out, but no luck. Correct answers are sometimes output as wrong, and I still have no way of actually inputting operator into the question it asks the user. Getting closer though maybe. Revised code:

    Code:
    #include <iostream>
    
    float divide (float x, float y); //function to divide numbers
    int multiply (int x, int y); //function to multiply numbers
    int add (int x, int y); //function to add numbers
    int subtract (int x, int y); //function to subtract numbers
    int generateRandomNumber(); //generates random number which will then be used as a condition to use an operator i.e. if 3, then multiply, if 4, then divide.
    
    int main()
    {
        int x; //local variable to store users first chosen number
        int y; //local variable to store users second chosen number
        int userGuess; //local variable to store the users attempt at answering question
        int answer; //local variable to store asnwer to random math question
        char anotherGo = '1';
        
            do
            {
                std::cout << "Please enter a number: ";
                std::cin >> x;
                std::cout << "Please enter another number: ";
                std::cin >> y;
                
                int generateOperator = generateRandomNumber(); //generates random number between 1-4, used in following conditions to trigger different functions
                
                if (generateOperator == 1)
                {
                    answer = divide(x,y);
                }
                else if (generateOperator == 2)
                {
                    answer = multiply(x,y);
                }
                else if (generateOperator == 3)
                {
                    answer = add(x,y);
                }
                else
                {
                    answer = subtract(x, y);
                }
                
                std::cout << "What is " << x << " " << generateRandomNumber() << " " << y << "? "; //this line may not help to find the answer, have to check program for what the number printed corresponds to, i.e. add, multiply...!
                std::cin >> userGuess;
                std::cout << std::endl;
                
                if (userGuess != answer)
                {
                    std::cout << "Sorry, that's the wrong answer.";
                }
                else
                {
                    std::cout << "Correct!";
                }
                
                std::cout << "\nDo you want another go? 1 for yes, 0 for no: ";
                std::cin >> anotherGo;
                std::cout << std::endl;
                
                if (anotherGo == '0')
                {
                    anotherGo = '0';
                }
            
            } while (anotherGo == '1');
        
        std::cout << "Exit program";
    
    }
    
    float divide (float x, float y) //function to divide numbers
    {
        return x / y;
    }
    
    int multiply (int x, int y) //function to multiply numbers
    {
        return x * y;
    }
    
    int add (int x, int y) //function to add numbers
    {
        return x + y;
    }
    
    int subtract (int x, int y) //function to subtract numbers
    {
        return x - y;
    }
    
    int generateRandomNumber()
    {
        int randomNumber = rand() % 5;
        return randomNumber;
    }
    Stopping for the night now so if anyone could take a look at this latest one and maybe suggest why it doesn't work as expected, I'd very much appreciate that. Thanks.

  4. #4
    Registered User
    Join Date
    Apr 2011
    Posts
    62
    hum...ok, of the top of my head:

    ---its good that you are not a "put all in the main" guy like most beginners usually are (I certainly was) but there's no need to exaggerate and create functions that only returns a simple operation. Your goal should be to make the code as easy to read as possible and you are just making it needlessly extensive.

    --- the rand function needs to be seeded with a different seed every time you run the program if you expect it to produce different results. use srand() to do it. you should get used to checking the c++ reference to figure out how std functions work so here is the rand() link (you will also find there an example of how to use time() to ensure the seed keeps changing)

    --- still on rand: you are using rand%5 and only expect to get results from 1 to 4. try running this and see what happens:
    Code:
    for (int i=0;i<20;++i)
        std::cout<<rand()%5<<endl;
    --- to make the hole thing look cleaner I would sugest (besides getting rid of the ridiculous "one operation" functions) the use of switch:case instead of the "if else"s. make 2 functions:

    Code:
    char operation(int rand_gen_int){
    //returns "+", "-", "*", "/"
      switch (rand_gen_int) {
        case(1)://(...)
      }
    }
    
    double operation(int rand_gen_int){
    //returns the answer to the operation
      switch (rand_gen_int) {
        case(1)://(...)
      }
    }
    cheers
    Last edited by killme; 04-08-2013 at 05:30 PM.

  5. #5
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128
    Quote Originally Posted by killme View Post
    --- the rand function needs to be seeded with a different seed every time you run the program if you expect it to produce different results. use srand() to do it. you should get used to checking the c++ reference to figure out how std functions work so here is the rand() link (you will also find there an example of how to use time() to ensure the seed keeps changing)
    Will check that out.


    Quote Originally Posted by killme View Post
    Code:
    for (int i=0;i<20;++i)
        std::cout<<rand()%5<<endl;
    Lots of zeros in there, not quite what I expected!

    Quote Originally Posted by killme View Post
    --- to make the hole thing look cleaner I would sugest (besides getting rid of the ridiculous "one operation" functions) the use of switch:case instead of the "if else"s. make 2 functions:

    Code:
    char operation(int rand_gen_int){
    //returns "+", "-", "*", "/"
      switch (rand_gen_int) {
        case(1)://(...)
      }
    }
    
    double operation(int rand_gen_int){
    //returns the answer to the operation
      switch (rand_gen_int) {
        case(1)://(...)
      }
    }
    I have not reached the use of switch/case yet so not sure what this code does, will test later when I get back from work. Thanks for the input.

  6. #6
    Registered User
    Join Date
    Apr 2011
    Posts
    62
    Lots of zeros in there, not quite what I expected!
    yeah, basic math: "%5" outputs in the [0;4] interval, shouldn't be to hard for you to figure out how to manipulate the function to get any interval you want (you could make a randint(min,max) function that you can later copy/paste to other small projects).

    I have not reached the use of switch/case yet so not sure what this code does, will test later when I get back from work. Thanks for the input.
    switch/case is just another way to make "multiple choice" segments that looks cleaner than "if else" when you have a lot of different option, 4 option is not so bad and if/else works fine (it will also work on 20 options but it will be a lot harder to read).
    but I do stand by the function headers I gave you as a cleaner was to do things, just hide the if-else's in there.
    Last edited by killme; 04-09-2013 at 03:04 AM.

  7. #7
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128
    Sorry but you've lost me. Not sure what I need to keep and what to ditch.

    Code:
    char operation(int rand_gen_int){
    
    //returns "+", "-", "*", "/"
    
      switch (rand_gen_int) {
    
        case(1)://(...)
    
      }
    
    }
    
     
    
    double operation(int rand_gen_int){
    
    //returns the answer to the operation
    
      switch (rand_gen_int) {
    
        case(1)://(...)
    
      }
    
    }
    Not sure what you meant by hide the if/elses? Do I keep them and physically move them into the switch/case or do these 2 functions take care of all of it? I don't know how to return "+", "-", "*", "/" through this function. I used a random number before which was used to assign an operation.

    Do I still need this line 24:

    Code:
    int generateOperator = generateRandomNumber(); //generates random number between 1-4, used in following conditions to trigger different functions
    I'm sure once it's up and running it will make a whole lot more sense to me but right now I'm up the creek without a paddle.
    Last edited by samwillc; 04-09-2013 at 01:11 PM.

  8. #8
    Registered User
    Join Date
    Apr 2011
    Posts
    62
    when I say "hide the if/else's", I mean mean "hide them inside a function so you don't have to look at them in the main" (sorry about that).

    you can't return the operator, but you had a line:
    d::cout << "What is " << x << " " << generateRandomNumber() << " " << y << "? "
    that needs a char "+","-","*" or "/" to look nicer (right now it looks something like this: "what is 125 2 55? 70).

    I would advise you to make 3 functions:
    --1 to generate a random number (and like I said you can just do a general one that takes 2 arguments (int min and int max) instead of one that always produces between 1 and 4.
    --1 that takes the "question numbers" and the 1-4 "question option" and returns the answer (you will have the if else's "hidden" inside the function).
    --and another that takes the "question option" and returns a char that you can use in the "question line" (this too will have if else's inside).

  9. #9
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128
    Hi, I have kind of got something i.e. it works, but not a great deal of progress in getting this lot into functions:

    Code:
    #include <iostream>
    #include <cstdlib>
    
    int main()
    {
        float x; //local variable to store users first chosen number
        float y; //local variable to store users second chosen number
        int userGuess; //local variable to store the users attempt at answering question
        float answer; //local variable to store asnwer to random math question
        char anotherGo = '1';
        
        do
        {
            std::cout << "Please enter a number: ";
            std::cin >> x;
            std::cout << "Please enter another number: ";
            std::cin >> y;
            
            int randomNumber = rand() % 4 + 1; //generates random number between 1-4, used in following conditions to trigger different functions
            
            switch(randomNumber) {
                case 1:
                    answer = x / y;
                    break;
                case 2:
                    answer = x * y;
                    break;
                case 3:
                    answer = x + y;
                    break;
                case 4:
                    answer = x - y;
                    break;
            }
            
            char operatorToUse;
            
            switch(randomNumber) {
                case 1:
                    operatorToUse = '/';
                    break;
                case 2:
                    operatorToUse = '*';
                    break;
                case 3:
                    operatorToUse = '+';
                    break;
                case 4:
                    operatorToUse = '-';
                    break;
            }
            
            std::cout << "What is " << x << " " << operatorToUse << " " << y << "? ";
            std::cin >> userGuess;
            std::cout << std::endl;
            
            if (userGuess != answer)
            {
                std::cout << "Sorry, that's the wrong answer.";
            }
            else
            {
                std::cout << "Correct!";
            }
            
            std::cout << "\nDo you want another go? 1 for yes, any other nuber for no: ";
            std::cin >> anotherGo;
            std::cout << std::endl;
            
            if (anotherGo == '0')
            {
                anotherGo = '0';
            }
            
        } while (anotherGo == '1');
        
        std::cout << "Exit program";
        
    }
    
    int generateRandomNumber()
    {
        int randomNumber = rand() % 5;
        return randomNumber;
    }
    I tried function:

    Code:
    char generateRandomOperator (int randomNumber)
    {
        switch(randomNumber) {
            case 1:
                operatorToUse = '/';
                break;
            case 2:
                operatorToUse = '*';
                break;
            case 3:
                operatorToUse = '+';
                break;
            case 4:
                operatorToUse = '-';
                break;
        }
    }
    Which I thought would take the random number 1-4, and output a character /, +, -, *. It doesn't. Use of undeclared identifier 'operatorToUse'. Getting closer though.

    Regarding the random numbers, I think I will deal with that once I understand how switch/case works. Getting fairly confused and trying to talk myself through the code from top to bottom.
    Last edited by samwillc; 04-09-2013 at 02:13 PM.

  10. #10
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by samwillc View Post
    Which I thought would take the random number 1-4, and output a character /, +, -, *. It doesn't.
    That's bacause your function never returns anything. The compiler should warn about that.
    Kurt

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by samwillc View Post
    Which I thought would take the random number 1-4, and output a character /, +, -, *. It doesn't. Use of undeclared identifier 'operatorToUse'. Getting closer though.
    Well, you aren't quite understanding how a function works. You are currently trying to assign a variable that doesn't exist in the function.
    (Remember: variables only exist in the scope they're defined; so if they are declared inside a function, they live only in that function and not outside.)
    Generally, to implement a function, you would do:

    Code:
    z = f(x, y);
    
    T f(T2 x, T3 y)
    {
    	T4 z;
    	// Do something with x and y and store into z, eg z = x + y;
    	return z;
    }
    T1, T2, T3 and T4 are arbitrary types. They can be anything that fits for your problem, for example int. You don't need to take two parameters either. You can arbitrarily many or few.
    "return z" is the line that pushes the result from the function to the caller (for example, in your case, main).
    It is also possible to compact this because a return statement can contain an expression, so for example "return (x + y);" is also legal.

    Look a little more at functions to properly understand what I mean.
    Then take it as an exercise to fix your function in your code.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128
    Thanks for all the help everyone. Elysia is totally right, I don't fully understand the nature of functions but I will keep trying again and again until I do! I think I may have nearly cracked it, whether it's a 'good' solution or not is unknown. This is the latest:

    Code:
    #include <iostream>
    #include <cstdlib>
    
    int generateRandomNumber();
    float getAnswer(int x, int y, int randomNumber);
    char getOperator(int randomNumber);
    
    int main()
    {
        float x; //local variable to store users first chosen number
        float y; //local variable to store users second chosen number
        int userGuess; //local variable to store the users attempt at answering question
        char anotherGo = '1';
        
        do
        {
            std::cout << "Please enter a number: ";
            std::cin >> x;
            std::cout << "Please enter another number: ";
            std::cin >> y;
            
            int randomNumber = generateRandomNumber(); /*generates random number between 1-4 to 
                                                        then generate random operator*/
            
            float answer = getAnswer(x, y, randomNumber); /*takes arguments of the 2 user chosen numbers and
                                                           uses them to output 1 of 4 different equations, randomNumber
                                                           is used to randomly choose an equation based on the number
                                                           chosen (switch/case)*/
            
            char outputOperator = getOperator(randomNumber); /*randomNumber is also used to switch to different
                                                              cases to select the appropriate operator for the
                                                              equation selected function in getAnswer()
                                                              Note to self, learn how to write decent comments*/
            
            std::cout << "What is " << x << " " << outputOperator << " " << y << "? ";
            std::cin >> userGuess;
            std::cout << std::endl;
            
            if (userGuess != answer)
            {
                std::cout << "Sorry, that's the wrong answer.";
            }
            else
            {
                std::cout << "Correct!";
            }
            
            std::cout << "\nDo you want another go? 1 for yes, any other nuber for no: ";
            std::cin >> anotherGo;
            std::cout << std::endl;
            
            if (anotherGo == '0')
            {
                anotherGo = '0';
            }
            
        } while (anotherGo == '1');
        
        std::cout << "Exit program";
        
    }
    
    int generateRandomNumber()
    {
        int randomNumber = rand() % 5; //look into srand() as posted earlier
        return randomNumber;
    }
    
    float getAnswer (int x, int y, int randomNumber)
    {
        switch(randomNumber) {
            case 1:
                return x / y;
                break;
            case 2:
                return x * y;
                break;
            case 3:
                return x + y;
                break;
            case 4:
                return x - y;
                break;
        }
    } //control may reach end of non-void function
    
    char getOperator(int randomNumber)
    {
        switch(randomNumber) {
            case 1:
                return '/';
                break;
            case 2:
                return '*';
                break;
            case 3:
                return '+';
                break;
            case 4:
                return '-';
                break;
        }
    } //control may reach end of non-void function
    I have had problems in the variables being out of scope and have been trying hard to get my head around that. I included the warnings I get in the above code but it does run, and does work, which I am fairly pleased about. I'm not expecting miracles in such early days.
    Last edited by samwillc; 04-09-2013 at 03:17 PM.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    "control may reach end of non-void function" simply means that the compiler is telling you that there is a path in the code such that the function never returns a value (hint: what if randomNumber is not 1, 2, 3 or 4?).
    In that case, the returned value is undefined and your code will behave strange.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    Apr 2011
    Posts
    62
    yes, apart from the random generator that still outputs 0 to 4, everything seems functional as far I can see, there are some inconsistencies that denote your lack of familiarity with the syntax but that comes with time.

    the most obvious "lesson" I can give you here is: "a function will stop running as soon as it gets a return instruction".

    so in your switch cases you can get rid of the "breaks", say your random number is 2, the function will run up to the "case (2):", get the return statement and simply ignore anything after that... it "won't even read" the other cases, so you don't really need the breaks

    as for the generator, it will probably be easier to just test the thing on its own till you get it, try making a new program somewhat like this and test:
    Code:
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    int randint(int min, int max);
    
    main{
      int min,max;
      cout<<"min:";
      cin>>min;
      cout<<"max:";
      cin>>max;
      for (int i=0;i<100;++i)
        cout<<randint(min,max)<<endl;     //its suppose to output 100 numbers in the [min,max] interval
      return 0;
    }
    testing things should be done separately to avoid confusions

  15. #15
    Registered User
    Join Date
    Jun 2012
    Location
    Morden, UK
    Posts
    128
    @Elysia, I tried adding:

    Code:
            default:
                return 0;
                break;
    This cleared the warning but I'm not sure whether this is a standard thing to do or not. I wonder when the random number would not be 1-4 though? Are you talking about future proofing, in case I wanted a bigger range and forgot to change the function accordingly?

    Code:
        int randomNumber = rand() % 4 + 1; //?? look into srand() as posted earlier
    I forgot to change the above line! I *think* this will output 1,2,3 or 4. Found another thread that might be useful too for this: http://www.cplusplus.com/forum/general/14192/

    @killme

    Useful to know about the functions, that will shorten the code a bit.

    Thanks for the other random number code too, I will whack that into another program and test
    Last edited by samwillc; 04-09-2013 at 04:01 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple Maths
    By r_james14 in forum C Programming
    Replies: 6
    Last Post: 03-16-2012, 09:11 PM
  2. Replies: 10
    Last Post: 10-03-2011, 11:05 PM
  3. Please help me on my simple program PSEUDO RANDOM NUMBERS
    By metaljacob in forum C Programming
    Replies: 21
    Last Post: 09-16-2010, 08:31 AM
  4. Understanding simple maths
    By FloatingPoint in forum C++ Programming
    Replies: 10
    Last Post: 08-06-2003, 07:38 AM
  5. Simple maths problem, did I do it right?
    By Zewu in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 10-21-2002, 12:12 PM