The C++ community is polarized about C++11's random-number facility
pcg-random.org
pcg-random.org
I don't think C developers should be sitting on a high horse on this one.
C represents a pretty good example of the problem. Almost every program that relies upon the standard C runtime's random functions has a flawed random distribution, so any correct program completely bypasses that infrastructure and/or has a ton of additional code/complexity layered on top of it.
That open source basically festered until the C++11 <random> proposal was accepted. The chief proponents of that proposal were, of course, those with the most sophisticated needs & understanding for random functions, and the proposal reflects that. So, the problems with that proposal are arguably a consequence of the flaws in the original C standard.
What remains to be done is to harmonize that proposal with something that makes sense to less sophisticated users, who nonetheless have reached the point where their appreciate the problems with C's random functions.
Right, and that function is a mistake in the C standard. It should have been omitted entirely.
Let's assume things had proceeded as you suggest though. We'd still not have a good solution for random number generation until the C++11 standard came out, and so we'd still have all the forces in place that gave rise to it and to the current mess.
See, for example, crypto before NaCl came around.
(NB: I'm not defending either this C++ standard or random(3).)
Sure... but what happens if you do specify that implementations should be built-in is that a diverse, bewildering ecosystem of broken implementations get built in, and so people who know what they're doing end up eschewing the built-in implementations in favour of shipping with an implementation which they know works. And ultimately you have a standard function which everybody provides for compatibility purposes, but which nobody should ever use. See, for example, random(3).
Functionality should be added to standards when we can be confident that every implementation in the next 100 years will get it right, and no sooner.
Although, I've never actually seen it used in the wild.
So, it leads me to guess there's two ways the the C++ situation would've been made unnecessary:
1. Leave it out of C itself but pro's build and maintain a de facto standard in form of a library as easy to use as random and widely available. Can even be OS random facilities cleanly wrapped.
2. Put a good one in C standard. Becomes the standard de facto and officially.
Preconditions didn't exist or convenience prevailed. So, now there's a new attempt at dealing with the mess. That's my guess as a person looking on from the outside rather than a user of all these tools. Just to be clear on that part.
However, eventually you need to provide something that works. There is some value in having a portable way to generate random numbers. I can't think of a language that doesn't define one, and I don't think that is by accident.
Man, autocorrect killed me there. That should be "That open sore".
So yeah, not exactly addressing the matter.
Of course, that whole arc4* library doesn't have the same challenges as a language standard, which is where a lot of the challenge here comes from.
(I don't write code where e.g. std::poisson_distribution would be useful, so I don't feel I have the background to have an opinion on that part of the proposal.)
Overflow is something that the programmer always has to keep in mind, unfortunately.
The proposal doesn't really care much about distributions. It's intended for people who don't care about random distributions.
Although we have different concerns, it's clear that a lot of thought has been put into the proposal, and it seems to achieve its/your goals pretty well. Don't let my concerns put you off.
To satisfy the two camps though (low level control vs "give me some sane default or package up common combinations") someone just writes the higher level API on top.
Or maybe your idea of "just the right amount of stuff" is different from someone else's idea of that, and we could be thankful that the world is able to accommodate more than one opinion on this by providing us with multiple programming languages we can use according to our needs and preferences.
C with nothing left to take away is portable assembly.
Also, instructions like 'estimate one over square root' have multiple 'correct' answers.
Edit: https://www-01.ibm.com/support/knowledgecenter/#!/ssw_aix_71... shows things are worse:
"The estimate placed into register FRT is correct to a precision of one part in 32 of the reciprocal of the square root of FRB. The value placed in FRT may vary between implementations and between different executions on the same implementation."
The specification, as far as I'm aware, gives no guarantees at all about the algorithm used. Why not just specify a good algorithm instead of adding a new function?
> The specification, as far as I'm aware, gives no guarantees at all about the algorithm used.
You are right about that. And, in fact, the few guarantees the standard has are weak enough that Microsoft ships a standards compliant implementation that is famously limited.
And this lets you (easily) generate more than just integers in the range [0, INT_MAX]. std::rand doesn't have that level of convenience.
There are all sorts of inconveniences with std::rand, and it looks like this solves the vast majority of them.
Adding other functions also doesn't fix std:rand. People use std::rand. They will continue to use std::rand, unless it's removed. And even then they'll keep using it, because implementations will add it back in for compatibility.
There's already a simple, half baked, crude random number generator. It's possible to fix it so that it provides at least acceptable randomness, and isn't complete junk. Doing this breaks nothing.
Why add another similar function with similar API issues?
C++11's random utilities and O'Neill's randutils aren't similar to std::rand at all. They're totally different beasts from std::rand.
Making std::rand a decent RNG would probably make the world a better place. I'm not disagreeing with that. But even if std::rand used a decent algorithm, it's still a suboptimal API.
I was kind of hoping that the `random_generator` class would be a templated class derived from a non-templated base class, so that it could be used in this manner. Looking over it, I can see why it doesn't, as many of the methods are much, much more useful as templated methods, which do not interact nicely with virtual functions.
I honestly am a bit at a loss though in terms of understanding how this proposal makes things significantly easier for programmers.
Absent this proposal, you would write:
std::default_random_engine e(std::random_device{});
std::uniform_int_distribution<int> uniform_dist(1, 6);
const int random_value = uniform_dist(e);
The new process basically cuts the first two lines down to one, and uses a method call for a uniform distribution instead of creating an object for it. Is that really easier?If so, then yeah, go with the idea of an empty constructor version of engines that will smartly seed from a random device, and add a mixin that does the magic of mapping all the different distributions in to methods.
I'm just wondering if that is somehow missing what is actually making life difficult for developers.
https://www.reddit.com/r/cpp/comments/31857s/random_number_g...
> One minor issue is that you’re using `default_random_engine`, which in some systems may be a LCG with a tiny 32-bit state. If so, you’ll have an RNG with a tiny period. That’s why Stephan recommends[1] that you explicitly use the Mersenne Twister. Of course, it might be something better, with more state.
> But what’s really wrong with it is that you use a single 32-bit integer to seed the RNG. If you’re using the Mersenne Twister, you’re using four bytes of state to try to seed 624 bytes. It’ll work, but it’s way worse than what the Python code does; Python uses 624 bytes of actual entropy rather than four bytes.
[1]: https://www.reddit.com/r/cpp/comments/31857s/random_number_g...
Seriously, the whole point of platform defaults is that they make appropriate choices for the platform. Sure, you can define your own engine, but that's exactly what the original API gives you...
That is super annoying.
rng.uniform(1,17)
I know exactly what to expect. Compare that to: uniform_dist(e);
Unless the variable is named very well ("UniformDistOneToSix"?), I don't know what that line does.Not to mention, what if I want to roll a bunch of numbers in a row? Do I create all the different distributions that I may ever need ahead of time? If I don't know what all random ranges I'll need, I guess I can just create them on the stack as needed, instantiating objects willy nilly. Eew.
I guess if it is really a mystery, you could just always do:
std::uniform_int_distribution<int>{1, 6}(e);
...and use some typedefs to avoid it being quite so verbose.I'm not sure I grok the bunch of numbers in a row scenario. Usually in that case I'd imagine you'd want to create a bunch of numbers with a consistent distribution, which is exactly why you have the structure you want. If not, you can always create new distributions in an ad hoc fashion (exactly why it is good that the parameters for a distribution are NOT template parameters). Instantiating distributions isn't costing you anything here. It's just a transient struct with a handful of fields... though if you use it for more than one call, it might somehow be more efficient (doubtful, but conceivable).
In practice, you pretty much always end up with something that holds the engine inside it, and you can always decorate it with methods like:
int roll_die(){ return std::uniform_int_distribution<int>{1, 6}(e); }
...or alternatively: template <typename T>
T uniform(const T begin, const T end) { return std::uniform_int_distribution<T>{begin, end}(e); }Isn't that almost a tautology? "People who care about X either love it or hate it".
I don't think this is correct either. How would thinking a problem is "not important whatsoever" imply that someone must love or hate any potential solution? I couldn't care less how sports team X fixes their losing record, and yet your claim is that that would somehow correlate with me having extreme opinions (love or hate) about their decision to draft Player Y? Very much to the contrary, I'm apathetic about any solution, which is pretty much the definition of finding a problem "not important whatsoever".
Furthermore, I'm not even sure how "extreme opinions of the problem's importance" is relevant to what we're talking about. The original quote was "to the extent that anyone cares about [the problem] at all". That's anywhere from "I care a bit" to "I care a ton", not exclusively "I care a ton".
Finally, even if you weren't very wrong about the premise of what we're talking about: "X is correlated with Y" doesn't mean "X implies Y is a tautology (or close to one) because they're the same thing", which is the original statement I was responding to.
> imply that someone must
Meh, correlation is not causation. Let's include apathy as a third extreme, for both problems and solutions.
Its a bug in MingW. Which isn't a big deal because Microsoft Visual Studio Community Edition is an excellent IDE and compatible with OSS projects now.
That's not really the case here, is it? If anything the bug is in the standard.
Windows has a non-deterministic source (IE: The function CryptGenRandom). Therefore, this is a bug in MingW's implementation. CryptGenRandom is hard to use, but that's no excuse for MingW's developers to be lazy.
Pointing at a "mistake" in the spec when the intent of the spec is extremely clear is laziness. Pure and simple.