Mac error with random number between 1 & 49

Hi,

When I create a random number (using 49 random number options) as per below - I always get the same result of 31 (but not when I use a number other than 49).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
	int num1;
	
	srand(time(0));
	num1 = 1 + rand() % 49;
	
	cout << num1 <<endl;
	
	return 0;
}


I have tried this on CodeRunner, CLion and CodeBlocks on my Mac and I get the error on all! When I try this on CodeBlocks on a PC then the number is random though...

Could this be an error with the compiler used by these apps on a Mac?
Last edited on
Do you mean that if you replace the 49 with, say 42, and run the program multiple times, you will not get the same result every time?
Exactly that - if I replace the 49 with another number then I get a different random number each time I run the program. But with 49 I always get 31 as the answer...
Strange hey??
That seems to work - with 1 to 49 too...
Still don't know why the other version does not though.

Must be a bug on the compiler I guess...
Don't use rand. There have been some shockingly bad implementations of it over the years.

https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
Thanks for that @Repeater - this guys is quite funny :)

Ah, now I know. Pity my university has put "rand" in our exercises - oops. Guess someone needs to inform them too ;)
Last edited on
if you've gotta use rand but srand(time(0)); isn't getting the job done, try this debugging:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
        int num1;
        cout << time(0) << "\n";
        srand(time(0));
        num1 = 1 + rand() % 49;

        cout << num1 <<endl;

        return 0;
}


Does the value printed for time(0) increment as you're running the program again at a later time?


Last edited on
Thanks @zaphraud

Yes, the line cout << time(0) << "\n"; is outputting a different number each time (seems to increment each second).

num1 is being output as 49 each time I run the code though... I changed the % 49 to % 50 and then num1 is a random number each time.

Definitely something to do with the number 49...
Forget the rand() - it's probably a red herring. Have you tested the result of any simple number modulo 49?
The multiplier being used in at least one of Apple's MCG random number generator is 16807.

https://en.wikipedia.org/wiki/Linear_congruential_generator

16807 is divisible by 49, which seems suspicious at first glance...

Here's more: https://stackoverflow.com/questions/20263187/rand-14-only-generates-the-values-6-or-13 , and this one has some interesting notes: https://stackoverflow.com/questions/7866754/why-does-rand-7-always-return-0

I suspect you are indeed suffering the effects of this atrocious rand implementation

When I try this on CodeBlocks on a PC then the number is random though...

Yup. rand is often just awful. I don't even use it for toy implementations that don't matter anymore; people often learn code by reading existing code and the risk that someone would use then use rand for something important without knowing the risks is too high!

Last edited on
Thanks @Repeater,

Yip, not using it even in toy applications due to others falling in the trap makes a lot of sense...

It is then still amazing that my university uses this... Guess they don't know any better. Or, maybe in a later module they will explain the better way and keep this in the first module just "because it is easy" (even if dodgy)...
I used to say, when confronted with it being used just for toy educational purposes, that it didn't really matter; it's obvious what it's meant to do, and using a bad implementation is fine because if people ever needed to actually generate high quality random numbers they wouldn't use rand() ; they'd do it properly.

However, having subsequently seen and read of serious instances in which shoddy random number generation was used through simply not knowing, I've come to the conclusion that people actually simply won't do it properly - generally because they just don't know. At least you now know.

If people don't want to watch STL's excellent talk on the subject, there's always the top half of this page: http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/
Last edited on
Thanks @Repeater - totally agree :)
closed account (E0p9LyTq)
Don't use rand.

When even the C standard says to not use it if there are better methods, rand is bad.

Quite a while ago someone gave me a link to a C++ working paper, "Three <random>-related Proposals"
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3547.pdf

One of the suggestions was "add to <random> the following modest 4-part toolkit of novice-friendly functions," and they list the 4 functions.

This was proposed back in 2013, and as far as I know C++14 nor C++17 included the suggestion. I doubt even C++20 (or whatever it will be titled when approved) will include it. So I mashed up my own header version of the proposal:

(I called it "random_toolkit.hpp):
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
#ifndef __RANDOM_TOOLKIT_HPP__
#define __RANDOM_TOOLKIT_HPP__

#include <random>
#include <chrono>

namespace rtk
{
   std::default_random_engine& urng()
   {
      static std::default_random_engine URNG { };
      return URNG;
   }

   void srand()
   {
      std::random_device rd;
      unsigned           seed;

      if (rd.entropy() != 0) // the implementation provides a usable random device
      {
         seed = rd();
      }
      else // no random device available, seed using the system clock
      {
         seed = static_cast<unsigned> (std::chrono::system_clock::now().time_since_epoch().count());
      }

      urng().seed(seed);
   }

   int rand(int from, int to)
   {
      static std::uniform_int_distribution<> dist { };
      using pt = decltype(dist)::param_type;
      return dist(urng(), pt { from, to });
   }

   double rand(double from, double to)
   {
      static std::uniform_real_distribution<> dist { };
      using pt = decltype(dist)::param_type;
      return dist(urng(), pt { from, to });
   }
}

#endif 

I have done some testing with it and it seems to work. cheetoblue's example program could be reworked into (with a little extra to test if your compiler has implemented std::random_device [GCC variants don't]):
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
#include <iostream>

#include "random_toolkit.hpp"

int main()
{
	// seed the random generator
   rtk::srand();
	
	// get a random integer number between 1 & 49 inclusive
   int inum = rtk::rand(1, 49);
	
   // get a random floating point number between 1 & 49 inclusive
   double dnum = rtk::rand(1.0, 49.0);
   
	std::cout << inum << ' ' << dnum << '\n';
	
	// let's check std::random_device's entropy (0 means not implemented)
	std::random_device rd;
	if (0 != rd.entropy())
	{
      std::cout << "I'm alive!\n";  
	}
	else
	{
	    std::cout << "Doin' the dead cockroach!\n";  
	}
}

minGW output:
37 17.9689
Doin' the dead cockroach!

Visual C++ 2017 output:
22 9.66962
I'm alive!
if you can force user interaction, there's always a random device.

versions of PGP I used during the 1990s asked users to type random things in order to generate a seed as they typed.
Off topic - but I would like to talk to cheetoblue. I am another Mac guy who is (slowly) learning to code in C++ to create some astronomy tools. You might look at this web page:

https://sites.google.com/site/macsatellitesoftware/home

and write me via the Contact Me page. It would be handy to ask some questions of another Mac user (we are rare, like fine wines).
Haha @CharlesPhillips - I guess we are hey ;) Will send you a message now...
Topic archived. No new replies allowed.