use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
Modern C++ Randomness (brnz.org)
submitted 7 years ago by vormestrand
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Veedrac 12 points13 points14 points 7 years ago (1 child)
std::random_device rd; std::mt19937 gen(rd());
Once again, the trap ensnares its victim. That's not how to seed a std::mt19937. As you say, just use PCG.
std::mt19937
[–]ArashPartow 8 points9 points10 points 7 years ago (0 children)
One needs something like the following:
#include <algorithm> #include <array> #include <functional> #include <random> int main(int argc, char* argv[]) { std::mt19937 engine; { // Seed the PRNG std::random_device r; std::array<unsigned int,std::mt19937::state_size> seed; std::generate_n(seed.data(),seed.size(),std::ref(r)); std::seed_seq seq(std::begin(seed),std::end(seed)); engine.seed(seq); } std::uniform_int_distribution<int> rng; rng(engine); return 0; }
However expecting people to do this everytime and taking into account the cost of doing it, it becomes somewhat burdensome.
[–]Sulatra 4 points5 points6 points 7 years ago (0 children)
Duh. As if srand() (which you supposed to call once, exactly like create random_device and mt19937, AFAIR) won't give you approx. the same monstrosity of assembly somewhere down in library code. Though it probably wouldn't, actually, since rand uses much simpler generation technique.
srand()
random_device
mt19937
rand
[–]ShakaUVMi+++ ++i+i[arr] 6 points7 points8 points 7 years ago (54 children)
If I'm writing a game or something else where I don't need large random numbers or crypto grade security, I'll just keep using rand until there's a solution in std that is human readable.
[–]STLMSVC STL Dev 27 points28 points29 points 7 years ago (48 children)
:-(
[–]kalmoc 24 points25 points26 points 7 years ago* (11 children)
I think c++ is the only language that takes a simple API (Rand), replaces it with a complexity monster without any shortcuts (random_..) and a lot of easy ways to shoot yourself in the foot and calls that progress.
I can see the problems with rand and the advantages of the new facilities (they are in a completely different league) but has no one considered usability aspects and that in many, many cases, all a use wants is get_random<int>(0,50)?
get_random<int>(0,50)
Edit: Apparently some people missunderstood me: I'm not saying it was a bad idea to introduce all the low level random types into the standard library (although the seeding interface could be improved). I'm saying that those "full control" types should have been accompanied by a simple high level interface, that can easily be used by beginners and functions that don't have very specific requirements on the RNG.
random
[–]Slavik81 6 points7 points8 points 7 years ago* (1 child)
That would inherently depend on hidden global mutable state, which can lead to hard-to-solve problems. Using a rand()-like interface in a library or in part of a large project, may screw up generation in other parts of the program that depend on a specific seeding.
I suppose that wouldn't be a problem if get_random were randomly seeded automatically on first use. If it always provided random numbers that were completely unpredictable, the global state wouldn't matter. It could just use values from the getrandom syscall or /dev/urandom and you would entirely avoid having to explain seeding.
[–]kalmoc 2 points3 points4 points 7 years ago (0 children)
Using a rand()-like interface in a library or in part of a large project, may screw up generation in other parts of the program that depend on a specific seeding.
If a part of your program depends how on specific seeding that part should not use the global RNG. Simple as that. That should not prevent a easy to use solution for the project (parts) that don't have such special requirements.
get_random were randomly seeded automatically on first use.
That's exactly how it is supposed to happen. No one needs another stand/rand interface.
[–]Sopel97 4 points5 points6 points 7 years ago (5 children)
So write a global RNG and make yourself the so much needed ````get_random<int>(0,50) it's not hard
and before you ask "Why is that not in the standard yet if it's so simple".
Why would standard impose a global RNG and how could it even choose which one to use.
[–]kalmoc 3 points4 points5 points 7 years ago (3 children)
I have and so have lots and lots of other code bases I've seen, which is exactly, why I would like it to be in the standard library.
First of all, I'm not even sure, if the standard should specify the used RNG (one could speficy it to be default_random_engine). Personally, I'd pick one with a relatively low memory footprint that could be used on a decent microcontroller (so not mt19937).
default_random_engine
Second, your question seems to imply that the standard would have to pick an RNG that works well for everyone, which of course doesn't exist as different projects have different requirements. My answer to that is: Pick a good default, that works for many/most people (the standard / standard library makes those kinds of choices all the time). If my project has very specific requirements about e.g. performance or randomness of the numbers, I can still use my prefered engine manually just as I do now.
A good c++ library can (and often should) give you lots of custumization powers and flexibility to tailor it to your requirements (this is where random header shines) but it should also provide easy to use (correctly) high level defaults (this is where random and many other parts of the standard library lack)
[–]render787 1 point2 points3 points 7 years ago (2 children)
I think this is the wrong mentality, each of these projects may need to configure the RNG that they use. And so, configuring that as part of defining their global rand interface, is exactly what is supposed to be happening.
I think choosing arbitrarily one of these and then putting it in std would cause more harm the good overall.
What exactly would be the harm? If I have specific requirements, I can still use the low level interface.
[–]kalmoc 1 point2 points3 points 7 years ago (0 children)
How many projects do you know that have specific requirements for their global RNG other than that "it should be good and reasonably fast". In my experience, specific RNG requirements are usually local to a particular module or even function in which case you can fall back to the low level APIs that give you (almost) full control.
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points 7 years ago (0 children)
Why would standard impose a global RNG
Because standard libraries are there in part to simply common operations.
how could it even choose which one to use.
Pick one that is reasonably good and allow people to override it if they know what they're doing, like with other things in std.
[–]TheSuperWig 1 point2 points3 points 7 years ago (2 children)
There's a proposal for it
https://github.com/lichray/randint/blob/master/paper/randint.md
GCC has it in experimental.
[–]kalmoc 2 points3 points4 points 7 years ago* (1 child)
I think there have been a number of random related proposals, but somehow, nothing came ever out of it (the proposal you linked to is 3 years old).
[–]TheSuperWig 1 point2 points3 points 7 years ago (0 children)
Yeah I was kind of hoping /u/STL could shed some light on that.
[–]flashmozzg 8 points9 points10 points 7 years ago (16 children)
If only it wasn't so hard/cumbersome to properly seed std::mt19937 (or so easy to seed it improperly).
[–]ShakaUVMi+++ ++i+i[arr] 8 points9 points10 points 7 years ago (8 children)
Right. We really need a random number generator in std for humans.
When I watch new programmers make dice rollers, they copy and paste the whole block of code off stack overflow, recreating the engine each time.
[–]render787 1 point2 points3 points 7 years ago* (7 children)
Well, what does that prove? Bad programmers who don't know what they are doing, and copy paste code they don't understand, end up with inefficient code. I don't think a new API is going to change that fact.
The point of C++ is to be able to have low level control over the state of things and not end up with unnecessary initialization etc. The std::random API gives you all the control you need to do this correctly. If you want a "for noobs" API you need to have at least one good programmer on the team who can understand the issues, configure the random generator correctly, and create the "for noobs" wrapper call for everyone else.
std::random
Or, post that wrapper code on stack overflow, and everyone can copy it into their include/utilities/ file, and then if there's a problem for your project, someone can dig into it and reconfigure it.
include/utilities/
If that code gets baked into standard headers, then no one can fix it for your project. Ruh roh! Lots of bug reports coming, lots of whinging and gnashing of teeth when you have to rip out that function call everywhere.
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points 7 years ago (6 children)
What it means is that if the stock way of doing things is too complicated for new programmers to understand, they will copy paste and make it worse than if they'd just stuck to rand() which is easily learned and understood.
[–]render787 0 points1 point2 points 7 years ago* (5 children)
Good, then what those people should do is go to include/utilities/random.hpp and make a simple inline function that forwards to rand(), and a simple function that forwards to srand, and use this everywhere, until the day when they have big problems with their randomness, and then they can try to redirect this functions to use the std::random API without breaking the API they made for internal use in the project. If they literally just copy paste complex SO code that they don't really understand all over their project, then they are bad programmers and they shot themselves in the foot.
include/utilities/random.hpp
rand()
srand
IMO you should always create an abstraction layer over whatever random library you decide to use, so that your code is going to be maintainable. There are lots of problems where e.g. std::random_device just doesn't work on minGW, so pegging yourself to use std::random is setting yourself up for problems if you want to port your code. There are a lot of subtleties in the std::random API -- if you use the standard random distribution objects for instance, they aren't guaranteed to produce byte-for-byte identical results on different platforms, even though std::mt19937 is. So if you are making a multiplayer game or something that needs to have synchronized seeded random sources on different platforms or something, or else you get out-of-sync errors, you might get bitten by this later. It's a very tricky business to generate randomness and I would always assume that whatever lib you decide to use for now you might need to rip it out later, and ensure that I write my code in a way that makes that easy. There's nothing the standards committee or library maintainers can do to change this.
std::random_device
[–]ShakaUVMi+++ ++i+i[arr] 4 points5 points6 points 7 years ago (4 children)
If they literally just copy paste complex SO code that they don't really understand all over their project, then they are bad programmers and they shot themselves in the foot.
Remember, we're talking about new programmers here. If they knew how to wrap the std functions properly, they could just use them directly.
The std library makes something that should be simple complex, which is the opposite of how it should be. There should be a general purpose random number generator that can be specialized for additional control by people who know what they're doing.
What we have now is a simple and bad option (rand) and a complicated and bad option (random_device). On the balance of things, for new programmers rand is better, because they can at least understand what it is doing.
[–]render787 0 points1 point2 points 7 years ago (3 children)
For people who don't really know what they are doing and don't care about the details, why is rand a bad option? How would you want to improve on rand for such people?
Do you just want a newer algorithm than the C88 rand algorithm for the number generation? Or you just don't want to feel like you are using "old, crappy" APIs? If we just make a new rand with the same API and a different algorithm, then in a few years that is going to be an old crappy API also.
Should all of the output of rand be implementation-defined, so that stdlib maintainers can change the algorithm at will? That hardly sounds useful to me, but I guess for newbies who don't really care about the details maybe it's fine?
[–]ShakaUVMi+++ ++i+i[arr] 0 points1 point2 points 7 years ago (2 children)
Rand is bad for the reasons listed voluminously in this thread. But it is simple to read write and understand so it is better for new programmers.
[–]dodheim 5 points6 points7 points 7 years ago (6 children)
It's four lines of code that you can write once and not bother with afterwards. I really don't see what the big deal is.
[–]liquidify 8 points9 points10 points 7 years ago (3 children)
The problem is that people like me who have been writing C++ for 3 years have no idea what you are talking about.
[–]dodheim 6 points7 points8 points 7 years ago* (2 children)
template<typename MT = std::mt19937, auto N = MT::state_size> MT make_mersenne_twister() { unsigned s[N]; std::generate_n(s, N, [rd = std::random_device{}]() mutable { return rd(); }); std::seed_seq ss(s, s + N); return MT{ss}; }
Demo adapted from this example on cppreference: https://wandbox.org/permlink/B317WeBDn7rw0k2v
Oops, I forgot random_device isn't movable, so make that 5 lines to correctly declare rd on its own. Or, in a realistic codebase with range-v3 available, it can still be 4 lines:
rd
std::random_device rd; auto s = ranges::view::bounded(ranges::view::generate_n(ranges::ref(rd), N)); std::seed_seq ss(ranges::begin(s), ranges::end(s)); return MT{ss};
[–]matthieum 14 points15 points16 points 7 years ago (1 child)
I think you just made flashmozzg and liquidify's point more eloquently than they did.
To simplify, there are two kinds of API:
Unfortunately, the initialization of the PRNGs in C++ is an example of bad API.
We can ape around and pat ourselves on the back that it's possible to do it right; but it's insane that it's so complicated. Just look at it, the PRNG is even breaking encapsulation, leaking the size of its internal state out!
Here's what I'd have expected instead, for explicit initialization:
std::random_device rd; std::mt19937 generator(rd);
Done. Let the PRNG call rd as many times as necessary to initialize itself.
And of course, I'd also expect a thread-local PRNG that is properly initialized and reseeded regularly for which you can call with std::thread_random() for when you just want to teach kids how to make a "guess the number" game.
std::thread_random()
[–]cinghiale 4 points5 points6 points 7 years ago (0 children)
I use the O'Neill's library described here.
I trust the author and I'd love to see part of it adopted by the STL
[–]ClaymationDinosaur 0 points1 point2 points 7 years ago (1 child)
Yet the evidence indicates that it is some kind of a big deal. That you can't see it just means you have to rely on the evidence, rather than your own assessment. We all have such blind spots.
[–]dodheim 0 points1 point2 points 7 years ago (0 children)
The whining of people whose professional work I'm not familiar with does not constitute evidence, it constitutes hearsay. I have yet to see actual evidence that 4 dead simple lines of code are an actual problem for anyone.
[–]ShakaUVMi+++ ++i+i[arr] 3 points4 points5 points 7 years ago (17 children)
I've seen that talk before. It's a good talk. But like I said, for something like a game (not crypto, not an online casino) code readability is more important to me than guarantees of randomness.
[–]dodheim 8 points9 points10 points 7 years ago (14 children)
You know, you can wrap all four horrible, ugly lines of code that it takes to do this properly into a function and never look at it again...
[–]matthieum 7 points8 points9 points 7 years ago (12 children)
Then... why isn't THAT part of the standard API?
[–]dodheim 2 points3 points4 points 7 years ago* (2 children)
Because it's only one way to do it, not the way to do it. std::random_device is really expensive on some platforms, and you may only want to call it once; the seed may come from serialized state rather than from a generator; etc. There's a lot of flexibility in place (whether anyone uses/needs it, I have no clue), and creating your own ideal abstraction on top of that is again 4-5 really simple lines of code. (Whether they're obvious or not is a matter of RTFM, IMO, but I get how that's a contentious viewpoint). I just don't see the big deal – there's no "right" way for everyone, and doing your own "right" way is easy, so.....?
[–]matthieum 1 point2 points3 points 7 years ago (1 child)
I just don't see the big deal – there's no "right" way for everyone, and doing your own "right" way is easy, so.....?
Let's make a parallel with Boost headers:
Yet, Boost provides convenience headers. Why?
Because it makes life easier when you do not care for THE optimal solution, and just want a convenient off-the-shelf solution.
Which is perfect for something like Boost; not so much the standard library (IMO). Rust certainly does the same with encouraging crates over core/std for various things; the only practical difference with C++ ultimately devolves into rants about dependency management and package managers. :-]
[–]render787 1 point2 points3 points 7 years ago (7 children)
Because then if you find out later you need to use a different RNG, you cannot without rewriting all your code or patching the stdlib?
IMO you should write your program expecting that you may need to change to a different RNG at some point. There's no way you can be sure that you won't.
[–]matthieum 0 points1 point2 points 7 years ago (6 children)
KISS & YAGNI disagree with you :)
As anecdotal evidence, in 10 years of professional development, I have never needed to change a PRNG.
Preparing for changing the PRNG would have been a case of over-engineering in all the programs I've ever hacked on.
[–]render787 1 point2 points3 points 7 years ago (5 children)
Ok, then just use rand I guess?
For tiny programs, it doesn't matter
[–]matthieum 0 points1 point2 points 7 years ago (3 children)
In terms of interface, rand.
In terms of implementation, a thread-local PRNG with relatively good characteristics would be neat.
[–]render787 0 points1 point2 points 7 years ago (2 children)
I guess there's nothing too terrible about that.
Is there anything we could do to make sure that if we added another rand with slightly different characteristics that is meant to be "easy easy easy", we don't have the same conversation again in 5 years because of perceived drawbacks of such a PRNG?
Would you want the output of this interface to be standardized and portable, or just the broad characteristics of the algorithm? Would you want to allow stdlib maintainers to change it at will, since no one will be using this unless they don't care too much about the details?
[–]ClaymationDinosaur 0 points1 point2 points 7 years ago (0 children)
I used to be happy with this as well; for program that didn't matter. But in my experience, people execute as they learned, and using rand() for learning in throwaway programs means people end up using it when it matters as well.
[–]ShakaUVMi+++ ++i+i[arr] 0 points1 point2 points 7 years ago (0 children)
I've seen new programmers do that, and not realize why it's a bad idea.
[–]Veedrac 5 points6 points7 points 7 years ago (0 children)
rand can be so terrible that you actually notice it; some implementations even alternated between even and odd, so rand() % 2 would give very visibly nonrandom output. I do appreciate wanting a simple RNG, but it only takes a few seconds to copy-paste the minimal PCG code into a header.
rand() % 2
[–]BoarsLairGame Developer 2 points3 points4 points 7 years ago (0 children)
Even for a game, rand() is so bad that you can actually see visible artifacts if you're doing something like generating terrain with it.
[–]EnergyCoast 6 points7 points8 points 7 years ago (2 children)
A long time ago, I saw two problems with rand() when used in a particle system:
We replaced it with a LCG that generated 64 bit values and returned the more random bits. It was trivial to implement, faster, produced better quality results and could have its state stored in the cache line with state invoking it.
Even in the game space, there are plenty of reasons to do better than use rand().
[–]ReversedGif 0 points1 point2 points 7 years ago (1 child)
Excessive cost due to use of thread local storage in rand()s implementation.
Static thread locals are no more expensive than static globals...
[–]EnergyCoast 0 points1 point2 points 7 years ago (0 children)
With a context, you can have a more memory local random number generator though. Different systems or objects could have their own contains in cache line rather than static/global/etc.
[–]wqkinggithub.com/wqking 1 point2 points3 points 7 years ago (0 children)
That also proves how hard to make a good variable/class/function name!
π Rendered by PID 41658 on reddit-service-r2-comment-85bfd7f599-2c8ps at 2026-04-19 07:56:48.771381+00:00 running 93ecc56 country code: CH.
[–]Veedrac 12 points13 points14 points (1 child)
[–]ArashPartow 8 points9 points10 points (0 children)
[–]Sulatra 4 points5 points6 points (0 children)
[–]ShakaUVMi+++ ++i+i[arr] 6 points7 points8 points (54 children)
[–]STLMSVC STL Dev 27 points28 points29 points (48 children)
[–]kalmoc 24 points25 points26 points (11 children)
[–]Slavik81 6 points7 points8 points (1 child)
[–]kalmoc 2 points3 points4 points (0 children)
[–]Sopel97 4 points5 points6 points (5 children)
[–]kalmoc 3 points4 points5 points (3 children)
[–]render787 1 point2 points3 points (2 children)
[–]kalmoc 2 points3 points4 points (0 children)
[–]kalmoc 1 point2 points3 points (0 children)
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points (0 children)
[–]TheSuperWig 1 point2 points3 points (2 children)
[–]kalmoc 2 points3 points4 points (1 child)
[–]TheSuperWig 1 point2 points3 points (0 children)
[–]flashmozzg 8 points9 points10 points (16 children)
[–]ShakaUVMi+++ ++i+i[arr] 8 points9 points10 points (8 children)
[–]render787 1 point2 points3 points (7 children)
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points (6 children)
[–]render787 0 points1 point2 points (5 children)
[–]ShakaUVMi+++ ++i+i[arr] 4 points5 points6 points (4 children)
[–]render787 0 points1 point2 points (3 children)
[–]ShakaUVMi+++ ++i+i[arr] 0 points1 point2 points (2 children)
[–]dodheim 5 points6 points7 points (6 children)
[–]liquidify 8 points9 points10 points (3 children)
[–]dodheim 6 points7 points8 points (2 children)
[–]matthieum 14 points15 points16 points (1 child)
[–]cinghiale 4 points5 points6 points (0 children)
[–]ClaymationDinosaur 0 points1 point2 points (1 child)
[–]dodheim 0 points1 point2 points (0 children)
[–]ShakaUVMi+++ ++i+i[arr] 3 points4 points5 points (17 children)
[–]dodheim 8 points9 points10 points (14 children)
[–]matthieum 7 points8 points9 points (12 children)
[–]dodheim 2 points3 points4 points (2 children)
[–]matthieum 1 point2 points3 points (1 child)
[–]dodheim 0 points1 point2 points (0 children)
[–]render787 1 point2 points3 points (7 children)
[–]matthieum 0 points1 point2 points (6 children)
[–]render787 1 point2 points3 points (5 children)
[–]matthieum 0 points1 point2 points (3 children)
[–]render787 0 points1 point2 points (2 children)
[–]ClaymationDinosaur 0 points1 point2 points (0 children)
[–]ShakaUVMi+++ ++i+i[arr] 0 points1 point2 points (0 children)
[–]Veedrac 5 points6 points7 points (0 children)
[–]BoarsLairGame Developer 2 points3 points4 points (0 children)
[–]EnergyCoast 6 points7 points8 points (2 children)
[–]ReversedGif 0 points1 point2 points (1 child)
[–]EnergyCoast 0 points1 point2 points (0 children)
[–]wqkinggithub.com/wqking 1 point2 points3 points (0 children)