8 ms·
The C++ community is polarized about C++11's random-number facility
- ww2 11y agoI do not like it because http://stackoverflow.com/questions/18880654/why-do-i-get-same-sequence-for-everyrun-with-stdrandom-device-with-mingw-gcc4 http://stackoverflow.com/questions/18880654/why-do-i-get-sam...
- dragontamer 11y agoBecause Microsoft implemented random_device correctly while MingW / GCC hasn't? 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.
- deleted 11y ago[deleted]
- aurhum 11y agoCould you point to the gcc bug? Note: the standard does not require a non-deterministic random_device, at least C++11 doesn't, so the behaviour as described in the stackoverflow link would be allowed.
- comex 11y agoThere are a lot of things the C and C++ standards allow implementations to do, such as making int 16 bits, using one's complement for signed integers, (in C) only making the first 31 characters of identifiers significant, (in C++) not allowing any identifiers longer than one character, except those in the standard library, et cetera. This is because they are designed to be portable to a wide variety of compilers and target devices which might have limits that weren't envisioned at the time of writing the standard. Doesn't mean it's a good idea to write absolutely pathological implementations for no real reason other than laziness...
- aurhum 11y ago>This is because they are designed to be portable to a wide variety of compilers and target devices which might have limits that weren't envisioned at the time of writing the standard. That's not really the case here, is it? If anything the bug is in the standard.
- dragontamer 11y ago> std::random_device may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. 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.
- cbsmith 11y agoI'd think the autoseed proposal in this post addresses that problem.
- santaclaus 11y agoI wish they had mandated the algorithms used in the distributions. Even with the same generator initialized with the same seed, the normal distribution, for example, will give different results across platforms. At least the results of the generators are consistent across platforms.
- Someone 11y agoIs that feasible for distributions over the reals across CPU architectures or maybe even revisions? FPUs typically do not compute the best possible result for floating point operations. Also, instructions like 'estimate one over square root' have multiple 'correct' answers. Edit: https://www-01.ibm.com/support/knowledgecenter/#!/ssw_aix_71/com.ibm.aix.alangref/idalangref_frsqrte_instrs.htm 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."
- api_or_ipa 11y agoIs this an indication of a randomly seeded Newtown's method?
- Someone 11y agoBut why would they? My guess would be that they don't bother to clear a carry flag or are computing the estimate using a few extra significant bits, and do not bother to initialize those at start, but that's 100% guess. I know very little about designing CPUs.
- cperciva 11y agoFeatures like this make me think that C++ is designed by people who think that perfection is reached when there is nothing more to add. As a C developer, I side with Antoine de Saint Exupéry.
- cbsmith 11y agoSigh... Too often that criticism is leveled at C++ without an understanding of the terrain. 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.
- cperciva 11y agoAlmost every program that relies upon the standard C runtime's random functions has a flawed random distribution Right, and that function is a mistake in the C standard. It should have been omitted entirely.
- cbsmith 11y agoThat would have messed with C++'s goal of providing compatibility for C code. 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.
- 11y ago
- GFK_of_xmaspast 11y ago"To the extent that anyone cares about C++11's random-number facility at all, the C++ community is polarized between two views—one that likes it, and one that hates it." Isn't that almost a tautology? "People who care about X either love it or hate it".
- forrestthewoods 11y agoThere's a wide spectrum between love and hate.
- wutbrodo 11y agoNo. You can recognize the importance of something and care about it a lot while thinking it's (eg) mediocre. Thinking a problem is important and having an extreme opinion of a solution are entirely different axes.
- isolate 11y agoIn my experience, having an extreme opinion of a problem's importance (very important, not important whatsoever) is correlated with having an extreme opinion of a solution (love it, hate it).
- wutbrodo 11y ago> having an extreme opinion of a problem's importance (very important, not important whatsoever) is correlated with having an extreme opinion of a solution (love it, 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.
- dicroce 11y agoI like this proposal and I agree that randint is a bad idea.
- cbsmith 11y agoI think there is a case to be made for doing both. The one advantage of randint is that it makes for a convenient migration path for those relying on std::rand() and friends. 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.
- deleted 11y ago[deleted]
- com2kid 11y agoThe current way separates out what will be gotten back from the engine from the actual invocation. In comparison, the proposal lets me look at one line and know what will be returned: 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.
- cbsmith 11y agoI'd just call it "from_one_to_six". 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); }
- MereInterest 11y agoOne thing that I would like to have is a common base class that can be passed around. Often, I would like for a function orclass to be told which engine to use, quite useful for unit testing, or for having reproducible results. As it is, the only way to accept multiple different engines is by templating over the engine type. This ends up requiring that every part of the code that uses the random engine be brought into the header file, and classes need to be templated on the engine type to store a reference to the engine. 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.
- starmole 11y agoI kind of agree! But think about performance. A fast pseudo random generator will/should create a random number in less cycles than one virtual function call has overhead. Also it's not hard to create your own virtual random class if you are willing to pay the price.
- deleted 11y ago[deleted]
- ori_b 11y agoWhy not specify the algorithm for std::rand? 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?
- cornstalks 11y agostd::rand has global state. Specifying the algorithm doesn't fix that. 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.
- ori_b 11y ago> std::rand has global state. Specifying the algorithm doesn't fix that. 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?
- cornstalks 11y agoWhat is this "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.
- maxlybbert 11y agoThey added more than a single new function. Personally, I like what was added. For what it's worth, I generally don't need to consult the documentation for the new random facilities (for a definition of "new" that includes "four years old"), but I do need to consult the docs for the stuff in <chrono>. > 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.
- kjf5091 11y agoTl;dr- clickbait title for a C++11 imitation of Pythons random-number facility >In fact, anything that's easy to do with Python's RNG class is just as easy to do here—in designing the class, wanted random number generation in C++ to become as easy as it is in Python >But don't just take my word for it, download randutils.hpp and play around. Start having actual fun with random number generation.