1

I had an assignment that required us to generate a three digit number twice so a student can add them together and then check their work. I am still very, very new to C++ and my class regretfully provided no information on how to even do this. He provided no videos, articles, or anything on randomly generating numbers, how to secure a specific number of digits, or even how to add them together.

The following is the code I cobbled together, as crude as it is. I cannot guarantee three digits. Every now and then, it will be a two digit number. I have already emailed him to see if he can point me in a correct direction, but I am not optimistic. I was thinking there would be some way I could set a minimum value, but after hours of searching for this, I could not find an answer.

#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;  //This is so I do not have to type std::

int main(void)
{
    int set1; 
    int set2;
    int sum=0;
    srand((unsigned) time(NULL)); // sets the random seed to provide different number utilizing the time of the computer

    set1 = rand() % 999 + 1; //creates a randomly generated three digit number
    set2 = rand() % 999 + 1; //created a randomly generated three digit number


    cout << "\n\n\n Are you ready for some math practice?\n\n\n";
    cout.width(8); //sets width of the columns to align everything
    cout << set1 << "\n"; //prints first generated set
    cout << " +   ";

    cout << set2 << "\n"; //[rints second generated set
    cout << "---------\n";
    cout << "\n\n\n";
    sum = set1 + set2; //add the two generated sets together
    cout << "Try to solve the problem. Have you got it?\n";
    system("Pause"); //waits for student to press enter to continue
    cout << "\n\n\n";
    cout << "The answer is: "; 
    cout << sum; //displays sum of two numbers
Pang
  • 8,605
  • 144
  • 77
  • 113
Chris
  • 11
  • 2
  • 2
    Why not just generate a random number between 0 and 899, then add 100 to it? – MrEricSir Feb 27 '18 at 04:37
  • You're close: `rand() % 999` will generate a number between `0` and `998`. Instead, you should probably generate a number between `100` and `898` (`rand() % 899 + 100`) then add `100`. Someone will likely answer with better mish-mash than what I've written though. – Tas Feb 27 '18 at 04:37

2 Answers2

3

The usual C method

This is what you are using. You need three pieces of information:

  • minimum value. For you it is 100. (The first three-digit number.)
  • maximum value. For you it is 999. (The last three-digit number.)
  • range, which is (maximum - minimum + 1). For you, that is (999 - 100 + 1) → 900.

To compute it the C-method way, compute the remainder of division by your range and add the minimum value. That is:

set1 = rand() % 900 + 100;

Any number modulo 900 gives you a value in 0..899. Add 100 and you get a number in 100..999. Voilà!

The correct C method

The above method suffers from bias (thanks to the Pigeonhole Principle). The way to fix it is to simply pull random numbers until you get one in the desired range:

int random_in_range( int minimum, int maximum )
{
  int result;
  do result = rand();
  while (result < minimum || maximum < result);
  return result;
}

Now you can simply ask for the number you want:

set1 = random_in_range( 100, 999 );

The only caveat is very small ranges (like 0..3) may produce noticeable lag; you will want to be a little more sophisticated about that. (Such as ask for numbers in 0..399 and divide by 100.)

The C++ method

Since you are using C++, you might as well learn how to do it properly.

#include <chrono>
#include <random>

int random_in_range( int minimum, int maximum )
{
  thread_local std::ranlux48 rng( 
    std::chrono::system_clock::now().time_since_epoch().count() );
  return std::uniform_int_distribution <int> ( minimum, maximum )( rng );
}

...

set1 = random_in_range( 100, 999 );

Here we use a static (thread-safe — if you only have one thread just use the word static instead of thread_local) pseudo-random number generator, and we get a number from it using a uniform integer distribution in the range given by the minimum and maximum value desired.

It is all wrapped up in a convenient function so it looks the same when using it as in the C version, but it is much nicer in terms of:

  • bias
  • speed
  • quality

In all cases...

you can use your existing code in the same way: Generate two random three-digit numbers, ask the user to input their sum and compare his answer to yours.

Dúthomhas
  • 4,323
  • 2
  • 11
  • 25
  • About the *correct* C method, you can use something like: https://stackoverflow.com/a/11766794/4944425 – Bob__ Mar 14 '18 at 09:57
2

You're very close!

set1 = rand() % 999 + 1; //creates a randomly generated three digit number

This actually generates a random number between 1 and 999. What you want instead is to generate a number between 100 and 999, and the easiest way to do that is to generate a number between 0 and 899 then add 100:

set1 = rand() % 900 + 100; //creates a randomly generated three digit number

rand() is fine for your purposes, but you can make this even clearer and get better results by using uniform_int_distribution

#include <random>
#include <iostream>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(100, 999); // our distribution is between 100 and 999
    // print 100 random numbers to test
    for (int i = 0; i < 100; ++ i)
        std::cout << dis(gen) << "\n";
}
Tas
  • 6,589
  • 3
  • 31
  • 47