Thread: using <random> properly

  1. #1
    Registered User
    Join Date
    Mar 2015
    Posts
    184

    using <random> properly

    I'm trying to switch to <random> instead of using the older rand(). After googling some examples I came up with function to generate an array of random ints between 1 and 10, but there's 2 problems.

    - When I generate an array of size 20, some elements always have the same value with repeated experiments.

    - The values far exceed 10 (by more than a million sometimes), and I also get zeros, but so far no negatives observed.

    without further ado:

    Code:
    template<size_t N>
      std::array<int,N> random_data(){
          std::array<int,N> arr; // I get only zeros when I brace initialize this
          //std::random_device rd;
          //std::mt19937 rg(rd());
          std::default_random_engine rg;
          std::uniform_int_distribution<> dist(1, 10);
          for (int x : arr ){x = dist(rg);}
          return arr;
      }
    
    //the code in main:
    auto mydata = random_data<20>();
      for (auto x : mydata) cout<<x<<"\n";
    Anyone see what I'm doing wrong?

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Well one of the major problems is that you may not be filling the array. This appears to be correct.
    Code:
    for (int &x : arr){ x = dist(rg); }
    You should use something other than random_device unless you are on a system that implements randomness. For instance, on cppreference, the following is given:
    Code:
     std::random_device rd2("/dev/random"); // much slower on Linux
        for(int n = 0; n < 10; ++n)
            std::cout << d(rd2) << ' ';
        std::cout << '\n';

  3. #3
    Registered User
    Join Date
    Mar 2015
    Posts
    184
    ah of course the reference. thanks! I need to use that range for loop more often...

    How do I know if my system implements randomness, and how big is the problem on systems that don't?
    Last edited by jiggunjer; 07-14-2015 at 01:10 PM.

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Well, the problem is the default engine can be anything. If you are on a system that implements randomness, you ought to know. See Hardware random number generator and the see also section.

    One of the things I also think you are forgetting is that you still need to seed your engine, and all the problems that come with doing that are still there.

  5. #5
    Guest
    Guest
    Quote Originally Posted by jiggunjer View Post
    How do I know if my system implements randomness, and how big is the problem on systems that don't?
    std::default_random_engine should define some random engine you can use, so this is not a problem. std::random_device is the shady one.

    As whiteflags said, you will need to seed your engine with changing values if you want changing sets of random numbers to be generated. You could for instance use the value returned by std::time, which changes at 1 second intervals, for that:
    Code:
    #include <ctime>
    
    rg.seed(std::time(nullptr));
    Last edited by Guest; 07-14-2015 at 01:45 PM.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Guest View Post
    std::default_random_engine should define some random engine you can use, so this is not a problem. std::random_device is the shady one.
    I don't find random_device shady at all. Why would it be shady?

    As whiteflags said, you will need to seed your engine with changing values if you want changing sets of random numbers to be generated. You could for instance use the value returned by std::time, which changes at 1 second intervals, for that:
    Much better is to actually initialize with a truly random seed, like one generated from std::random_device:

    Code:
    std::random_device rd;
    std::mt19937 engine{ rd() };
    std::uniform_int_distribution<int> dist(1, 10);
    for (auto & x : myarray)
        x = dist(engine);
    Of course, some stupid compilers fail to implement random_device correctly (I'm looking at YOU gcc!). In that case, you'll just have to fallback on std::time. Still, if you can avoid stupid compilers, random_device is MUCH better.
    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.

  7. #7
    Registered User
    Join Date
    Mar 2015
    Posts
    184
    Does that include g++ 5.1?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If you mean improperly implementing std::random_device, then yes.
    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.

  9. #9
    Guest
    Guest
    Quote Originally Posted by Elysia View Post
    If you mean improperly implementing std::random_device, then yes.
    That I meant. I recall having problems with it on Windows/MinGW when trying out <random> and then wondered why it was there in the first place.

  10. #10
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by Elysia View Post
    If you mean improperly implementing std::random_device, then yes.
    In what way is it improperly implemented?

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    After some checking, apparently it's not improperly implemented, it's just stupidly implemented since it returns the exact same sequence every time it's run.
    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 2015
    Posts
    1,640
    Quote Originally Posted by Elysia View Post
    After some checking, apparently it's not improperly implemented, it's just stupidly implemented since it returns the exact same sequence every time it's run.
    That sounds broken to me as it certainly isn't what one would expect. Apparently it's implemented with a pseudo-random number engine with a default seed, which I assume your checking determined was allowed. But it really shouldn't be allowed to use a fixed seed. I wonder if there's gcc compile-time options (I mean when building gcc itself) that turn on/off using an actual random device or not.

    I assume your testing it under mingw (or cygwin) so it may not be a general property of gcc.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by algorism View Post
    That sounds broken to me as it certainly isn't what one would expect. Apparently it's implemented with a pseudo-random number engine with a default seed, which I assume your checking determined was allowed. But it really shouldn't be allowed to use a fixed seed. I wonder if there's gcc compile-time options (I mean when building gcc itself) that turn on/off using an actual random device or not.
    Yeah, the standard allows it when there's no appropriate hardware available to generate true random numbers. That's why it's a stupid implementation since there are APIs in Windows that can give truly random numbers, and VC++ implements that, so why GCC doesn't is beyond me.

    I assume your testing it under mingw (or cygwin) so it may not be a general property of gcc.
    Yeah, it's mingw. As far as I know, this is only a problem under Windows.
    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
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Elysia View Post
    Yeah, the standard allows it when there's no appropriate hardware available to generate true random numbers. That's why it's a stupid implementation since there are APIs in Windows that can give truly random numbers, and VC++ implements that, so why GCC doesn't is beyond me.


    Yeah, it's mingw. As far as I know, this is only a problem under Windows.
    Well, now you know why I said you shouldn't use random_device. It works okay if you actually have hardware, or you can access something like /dev/random

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by whiteflags View Post
    It works okay if you actually have hardware...
    But that's the thing - every PC has "the hardware". It's just some stupid compiler that refuses to implement it properly.
    Regardless, yeah, don't use it if you need to use gcc.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. random question, random choices multiple choice
    By ccarlorafael in forum C++ Programming
    Replies: 7
    Last Post: 11-09-2013, 12:22 AM
  2. Random not working properly
    By KiRa11Love in forum C Programming
    Replies: 7
    Last Post: 08-10-2012, 04:00 AM
  3. Replies: 4
    Last Post: 11-16-2004, 07:29 AM
  4. Replies: 2
    Last Post: 12-25-2003, 01:31 AM
  5. Replies: 1
    Last Post: 12-14-2002, 01:51 AM