Generating different random numbers

Q= How do I generate random numbers that are different from each other in the following code?


srand(time(NULL));
a = rand()%maximumValue+1;
srand(time(NULL));
b = rand()%maximumValue+1;
cout << a << "+" << b << "= " ;
cin >> ans;
if (ans==a+b)
cout << "You win";
}

In the above code the variables 'a' and 'b' generate the same random numbers, and I want this to be done without the use of a function.
Remove the second call to srand.

Otherwise you will (almost always) be seeding your random number with the same thing twice, and hence generating the same random number in a subsequent call to rand().
Remove the second call to srand().

That will make it unlikely that you get duplicate random numbers, but the only way to be certain is to check for it. Something like:
1
2
3
4
5
srand(time(NULL));
a = rand()%maximumValue+1;
do {
    b = rand()%maximumValue+1;
} while (b == a);
Hello haiderasif123,


PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

Along with the proper indenting it makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button. This will not automatically indent your code. That part is up to you.


You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.


As lastchance and dhayden are saying "srand" only needs to be call ONCE at the beginning of the function and it is best put in the "main" function.

Also this is a better way to write "srand": srand(static_cast<size_t>(time(nullptr)));.

This video is worth watching. It explains the problems using "srand" and "rand"

https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

There is also:
https://web.archive.org/web/20180123103235/http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/

Andy
How do I generate random numbers that are different from each other
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
#include <iostream>
#include <random>

int main()
{
   int max_value { 125 };

   // let's create a C++ random engine
   // seeded with the output of a true random engine
   std::default_random_engine rng(std::random_device {}());

   // let's create a distribution for random numbers between
   // 1 and max_value
   std::uniform_int_distribution<int> dis(1, max_value);

   // let's generate a random number
   int a { dis(rng) };

   int b { };

   // a loop to eliminate the very slight possibility the two
   // random numbers are the same
   do
   {
      // let's generate a second random number
      b = dis(rng);
   }
   while (a == b);

   std::cout << a << " + " << b << " = ";
   int ans { };
   std::cin >> ans;

   if (ans == a + b)
   {
      std::cout << "You win!\n";
   }
   else
   {
      std::cout << "Wrong answer.\n";
   }
}
Also this is a better way to write "srand": srand(static_cast<size_t>(time(nullptr)));

To me, this just adds unnecessary verbiage. The compiler will do the case automatically. Or are there architectures where it won't?

As a side note, the Ada programming language did no automatic casts, so you had to cast everything explicitly.
Also this is a better way to write "srand"

All that does is shut up a compiler warning, NOT an error, a warning that srand requires an unsigned value passed. time returns a time_t value.
http://www.cplusplus.com/reference/ctime/time_t/

If someone wants to use the C library to generate random numbers might as well use C casting if the warning is too annoying. That is at least "consistent."
srand((unsigned)time(0));
Handy Andy wrote:
Also this is a better way to write "srand": srand(static_cast<size_t>(time(nullptr)));

That seems to match the C++ Core Guidelines spirit.

CppCoreGuidelines wrote:
C.164: Avoid implicit conversion operators

Reason Implicit conversions can be essential (e.g., double to int) but often cause surprises (e.g., String to C-style string).
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c164-avoid-implicit-conversion-operators

ES.49: If you must use a cast, use a named cast

Reason Readability. Error avoidance. Named casts are more specific than a C-style or functional cast, allowing the compiler to catch some errors.
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es49-if-you-must-use-a-cast-use-a-named-cast


Programming Principles and Practice wrote:
5.6.4 Narrowing errors
In §3.9.2 we saw a nasty kind of error: when we assign a value that’s “too large to fit” to a variable, it is implicitly truncated. [omissis] we can write a function that tests and throws a runtime_error exception if an assignment or initialization would lead to a changed value. For example:
 
char c1 = narrow_cast<char>(1066);      // throws 


8.5.7 Argument checking and conversion
[omissis] If you really mean to truncate a double value to an int, say so explicitly:
1
2
3
4
void ggg(double x)
{
    [omissis]
    int x3 = static_cast<int>(x);       // very explicit conversion (§17.8) 


17.8 Messing with types: void* and casts
[omissis] The name static_cast is a deliberately ugly name for an ugly (and dangerous) operation.

To my understanding, it’s advisable to make a cast explicit and loud, if possible.
char c1 = narrow_cast<char>(1066); // throws

In the GSL it's the opposite.
narrow_cast means I know that I might lose some data but I don't care.
char c1 = gsl::narrow<char>(1066); // throws narrow_cast

GSL: https://github.com/microsoft/GSL
@Learner2
Very right! Even if perhaps the main purpose of gsl::narrow is to ensure the type holds the same (let’s say, for example, no casting from floating points to integers).
This is the comment:
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value

This is an example code (the Microsoft gsl implementation you linked):
1
2
3
4
5
6
7
8
9
10
template <class T, class U>
[omissis]
T narrow(U u) noexcept(false)
{
    T t = narrow_cast<T>(u);
    if (static_cast<U>(t) != u) throw narrowing_error{};
    if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
        throw narrowing_error{};
    return t;
}


This is a perhaps related C++ Core Guidelines chapter:
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es46-avoid-lossy-narrowing-truncating-arithmetic-conversions
Note The guidelines support library offers a narrow_cast operation for specifying that narrowing is acceptable and a narrow (“narrow if”) that throws an exception if a narrowing would throw away information:
1
2
i = narrow_cast<int>(d);   // OK (you asked for it): narrowing: i becomes 7
i = narrow<int>(d);        // OK: throws narrowing_error 


We also include lossy arithmetic casts, such as from a negative floating point type to an unsigned integral type:
1
2
3
4
5
6
double d = -7.9;
unsigned u = 0;

u = d;                          // BAD
u = narrow_cast<unsigned>(d);   // OK (you asked for it): u becomes 4294967289
u = narrow<unsigned>(d);        // OK: throws narrowing_error 



- - -
Re-edit note: Mmmh! No, I was probably wrong. It explicitly verify the sign, anyway.

Last edited on
I find this gsl::narrow, very useful.
I actually found some bugs with it.
Topic archived. No new replies allowed.