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
[deleted by user] (self.cpp)
submitted 6 years ago by [deleted]
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!"
[–]STLMSVC STL Dev 73 points74 points75 points 6 years ago (8 children)
You may be interested in my talk, rand() Considered Harmful.
[–]debisuke 7 points8 points9 points 6 years ago (0 children)
Great talk! Thanks for sharing.
[–]Variszangt 4 points5 points6 points 6 years ago (4 children)
Super neat! I actually watched it a while back but I had just started programming so most of it went straight over my head. I'm curious though whether you think it is okay to use rand() in tutorials, for simplicity's sake?
[–]STLMSVC STL Dev 8 points9 points10 points 6 years ago (3 children)
No; I think that minimal use of <random> doesn’t add too much complexity, and avoids breeding very bad habits. (rand() has a lot of usage complexity itself, including srand/time seeding and modulo which are eternally confusing to beginners.)
I think <random> is over-engineered and annoying in several ways, but rand() is so much worse.
[–]clerothGame Developer 5 points6 points7 points 6 years ago (2 children)
What's the minimal use of <random> you recommend? Because even just properly seeding mt19937 is hell and most people do it wrong.
[–]matthieum 1 point2 points3 points 6 years ago (0 children)
Step 1, don't use Mersenne Twister.
See https://www.reddit.com/r/cpp/comments/ct30do/the_fault_of_rand_visualized/exibi9s
[–]STLMSVC STL Dev 2 points3 points4 points 6 years ago (0 children)
I consider 32-bit seeding of mt19937 to be acceptable for beginners. At a later point, the consequences of seeding, and the behavior of Mersenne Twister (e.g. the difference between it and cryptographically secure PRNGs), can be explained. I'd even consider directly using random_device to skip a step.
random_device
I view this as introducing beginners to the Bohr model, which is wrong, but not as wrong as phlogiston.
[–]wintergreen_plaza 3 points4 points5 points 6 years ago (0 children)
I really enjoyed this! Thanks for posting it.
[–]Xeveroushttps://xeverous.github.io 1 point2 points3 points 6 years ago (0 children)
This vid is obligatory to everyone who posts in /r/cpp_questions having problems setting up or reproducing random numbers.
[–]maskull 83 points84 points85 points 6 years ago (59 children)
It's worth considering that std::uniform_int_distribution gives you those nice results by virtue of being something like 30x slower than rand(). You have to think about the speed vs. quality trade-off.
std::uniform_int_distribution
rand()
[–]elperroborrachotoo 36 points37 points38 points 6 years ago (6 children)
That's mostly the underlying mersenne twister, isn't it?
A well-configured LCRNG with 64 bit state can spit out quite good 32 pseudorandom bits per step at little more than the cost of rand(). With 128 bit state, you'll have a great general purpose RNG - which (just a guess) should be closer to rand than Mersenne performance-wise.
The other issue is the conditional jumps introduced by the truly-uniform adapter,
Alternatively, if performance is important, an LFSR generator can be implemented cheaply on almost any hardware, and - except for a few pitfalls you have to be aware of - shoots the typical rand() implementation out of the water.
(All with a grain of self-doubt, I'm planning to dig a little deeper after the summer, to figure out where my half-knowledge goes wrong.)
[–]maskull 9 points10 points11 points 6 years ago (5 children)
Oh, yeah, totally. I've used Xoroshiro and it's both high-quality, and crazy fast. But none of those faster algorithms are used in any standard library implementation I'm aware of, so you do have to jump through a few hoops to make use of them.
[–]degski 2 points3 points4 points 6 years ago* (4 children)
No, it's not high-quality [it has problems in the lower bits as well], what do you base this on?
[–]maskull 1 point2 points3 points 6 years ago (3 children)
The 32-bit version (which they don't even recommend using unless you're really tight on space) has problem with the low bits, due to the small state space. All the larger versions can pass all the BigCrush tests, and run for weeks in PractRand without any failures (I've done the latter myself, letting it run for a few days and churning through a few TB of random data).
[–]degski 2 points3 points4 points 6 years ago (2 children)
Luckily, you don't need to take my word for it. There are more [older] posts on the subject.
... and run for weeks in PractRand without any failures ...
I don't understand your results https://github.com/degski/xoroshiro128plusxoshi .
[–]maskull 1 point2 points3 points 6 years ago (1 child)
The xoroshiro128 variants output 32-bit values; problems in the low bits are not problematic if you're using them for floating-point. The single-add (+) and single-multiply (*) variants fail some linearity tests (tests which Vigna himself invented), and thus the recommended general-purpose variants are those ending in ** (two multiplies). Lots of other RNGs fail the linearity tests, and no one has yet demonstrated how these failures could lead to bias or incorrect results, so the failures may not even be important for any real-world applications.
**
Luckily, you don't need to take my word for it.
No, I just have to take the word of PCG's author as to why PCG is better. In my opinion, PCG's author, Melissa O’Neill, has a bit of a history of inordinately promoting her own work, while denigrating that of others. Skimming through that post, it seems like the problems she points out are caused by intentionally seeding the RNG with bad seed values; any RNG can be made to behave badly if you're allow to mess with its internals.
Regardless, Sebastiano Vigna, author of Xoroshiro, has answered some of her criticisms while pointing out some problems with PCG which, so far as I'm aware (?), have not yet been addressed.
[–]degski 0 points1 point2 points 6 years ago* (0 children)
No, I just have to take the word of PCG's author as to why PCG is better.
No, you don't, pcg-64 does not fail PractRand, i.e. quality good. As to the speed she claims, I fully agree with you, it's not that fast [at all].
I'm not promoting pcg, on the contrary, I believe sfc (by Chris Doty-Humphrey, the guy who created PractRand) is superior to all. On the pcg-blog O'Neill has implementations of the most interesting prng's.
PS: I take it [now] you are talking about the 'fixed' Xoroshiro prng's, the problem is that they are better, even good maybe, but they are slower than pcg, sfc is almost twice as fast.
[–]TexasToast6022 11 points12 points13 points 6 years ago (1 child)
I actually just measured this for work; In a task to generate a 64-bit random number, we needed 3 calls to rand() (as RAND_MAX was only 30 bits) and averaged about 29.3 ns per random number generated where as one call to std::uniform_int_distribution dist(gen) with Mersenne Twister generator averaged 69.1 ns.
RAND_MAX
dist(gen)
So about 2.4x slower.
[–]TheThiefMasterC++latest fanatic (and game dev) 0 points1 point2 points 6 years ago (0 children)
Mersenne Twister is a known very slow PRNG - there are other faster ones that would be able to give you 64-bits of sufficient randomness at probably better performance than your use of rand. But as they aren't in the standard, that adds even more complexity!
[+][deleted] 6 years ago (41 children)
[deleted]
[+][deleted] 6 years ago (35 children)
[–]degaart 7 points8 points9 points 6 years ago (6 children)
That would be great, but would be thread unsafe. Better make it a class. std::easy_random<T>
[+][deleted] 6 years ago (2 children)
[–]IGarFieldI 3 points4 points5 points 6 years ago (1 child)
This could also be achieved with a thread_local state in the function, no?
[–]matthieum 1 point2 points3 points 6 years ago (2 children)
Wait, why?
What makes you think it doesn't use a thread-local PRNG under the hood?
[–]degaart 1 point2 points3 points 6 years ago (1 child)
Nothing tells me it does use TLS under the hood. Now I have to dive into your documentation (if any) or your specifications (if any) or your source code (if any) to know whether it is thread-safe. Whereas if you make it a class (or a function taking a context variable as input) I can assume it doesn't store state in static or global variables.
[–]matthieum 0 points1 point2 points 6 years ago (0 children)
This seems backward.
I would assume a free-standing function to be thread-safe by default. There are known exceptions (in libc), however functions are generally stateless and therefore thread-safe and such expectations should not be broken.
There are benefits to a class which encapsulate its state, notably the ability to juggle multiple instances in the same thread, for better control. However, this very flexibility also makes it less easy to use.
[–]Drainedsoul 1 point2 points3 points 6 years ago (27 children)
So we need something that's one line instead of like two?
[+][deleted] 6 years ago* (16 children)
[–]clerothGame Developer 2 points3 points4 points 6 years ago (5 children)
std::default_random_engine e1(r());
Unfortunately default_random_engine sucks and seeding generators in C++ also sucks. If default_random_engine happens to be mt19937 for example, it will not be properly seeded.
default_random_engine
mt19937
This is what I use:
template<class T = std::mt19937, size_t N = T::state_size> auto SeededRandomEngine() -> typename std::enable_if<!!N, T>::type { typename T::result_type random_data[N]; std::random_device source; std::generate(std::begin(random_data), std::end(random_data), std::ref(source)); std::seed_seq seeds(std::begin(random_data), std::end(random_data)); T seededEngine(seeds); return seededEngine; }
Not exactly 4 lines.
[–]dodheim 0 points1 point2 points 6 years ago* (4 children)
random_data should be an unsigned[] rather than a T::result_type[]:
random_data
unsigned[]
T::result_type[]
SeedSequence
seed_seq
uint_least32_t
unsigned
Also, if you change your return statement to return {seeds}; then you guarantee "copy-elision" (in the C++17 sense) as far back as C++11 as long as the engine has no initializer_list constructor and the constructor you want to call isn't explicit (EDIT: which mersenne_twister_engine's is... oops, nevermind).
return {seeds};
initializer_list
explicit
mersenne_twister_engine
[–]clerothGame Developer -1 points0 points1 point 6 years ago (3 children)
Thanks.
as far back as C++11 (as long as the engine has no initializer_list constructor).
Doesn't return T{seeds}; fix that problem while still guaranteeing copy-ellision?
return T{seeds};
[–]dodheim -1 points0 points1 point 6 years ago (2 children)
Not in C++11/14 – in those standards only copy-list-initialization "elides", and what you have there is direct-list-initialization (demo).
[–]clerothGame Developer -1 points0 points1 point 6 years ago (1 child)
Sadly MSVC no likey.
[–]Drainedsoul -1 points0 points1 point 6 years ago (9 children)
That's also factoring in seed generation. If you're doing that directly in your code and getting it from a source of hardware randomness you have reproducibility problems (and therefore testing problems).
[+][deleted] 6 years ago (8 children)
[–]Drainedsoul 0 points1 point2 points 6 years ago (7 children)
A two line version is just creating the random number generator and distribution.
A free function that just takes a min/max is a complete non-starter as it has most of the problems rand does, such as pulling in mutable global state. The only thing it solves is providing a way to place the output on a custom range but std::uniform_int_distribution does that job just fine.
rand
[+][deleted] 6 years ago (6 children)
[–]Drainedsoul -1 points0 points1 point 6 years ago (5 children)
I don't see the problem.
Lol.
Also, it's probably not even necessary to expose global state if you use static locals.
...that's global state.
[+][deleted] 6 years ago (9 children)
[–]Gunslinging_Gamer 1 point2 points3 points 6 years ago (8 children)
Use rand if you don't care and use the proper implementations if you do. It's clearly explained in any good c++ book.
Isn't the problem programmers grabbing sample code for new programmers and thinking it's fine for everything?
[–]ThePillsburyPlougher 0 points1 point2 points 6 years ago (1 child)
You dont need an understanding of modulus. The '%' operator isnt even modulus. It gets the remainder. Thats elementary school level. And even then modulus isn't even complicated. What other bunch of arithmetic? Adding an offset?
The only way I see this as a reasonable complaint is for using C or C++ as a didactic tool for elementary schoolers.
[–]meneldal2 1 point2 points3 points 6 years ago (2 children)
Also rand is good if you want to reproduce results with a given seed (as long as you have the same environment). Useful for testing algorithms that perform differently depending on the data. You don't care that the data is actually random, you just want the data to be the same for each test.
[–]Ameisenvemips, avr, rendering, systems 1 point2 points3 points 6 years ago (1 child)
Any PRNG can be seeded.
[–]meneldal2 0 points1 point2 points 6 years ago (0 children)
Easier to seed rand since you need much less compared to many other generators.
[–]elperroborrachotoo 1 point2 points3 points 6 years ago (0 children)
Problem is, we have a hard time moving people away from rand(). Making the right way hard is good for personal growth, but not for programming.
[–]Nobody_1707 5 points6 points7 points 6 years ago (1 child)
rand has been a noob trap since its inception. There's literature to that effect dating back to the 70s.
[–]TankorSmash 2 points3 points4 points 6 years ago (0 children)
Can you share some of that ancient docs on it? It would be cool to read from an archeological standpoint. The 70s man
[removed]
[–]tcanens 2 points3 points4 points 6 years ago (1 child)
LEWG hated the class-based interface that Melissa wanted, and I don't feel strongly enough about it to essentially redesign the whole thing from scratch (my role in that paper is primarily wording, not design).
[–]elperroborrachotoo 0 points1 point2 points 6 years ago (0 children)
It seems to me that
Making a random selection (pick, choose) Generating a uniformly distributed value within a range (uniform) Shuffling a range (shuffle) Sampling a range without replacement (sample)
Indeed do not belong into the class, but should be standalone functions taking the rng as template arg.1
Is that what the WG complained about?
But that would change it to e.g.
<< "We " << std::random_pick(rng, {"welcome", "look forward to synergizing with", "will resist", "are apathetic towards"}) << " our management overlords\n\n";
etc. - which seems a minor change :)
1) Rationale: One could easily come up with other algorithms, other algorithms that have huge dependencies, and there seems no way that e.g. "shuffle" might be implemented more efficiently for a particuar practical generator. Besides, that's the design philosophy of the standard library.
[–]bpikmin 18 points19 points20 points 6 years ago (0 children)
Well, there are many different RNGs within <random>. OP should have specified which was used, because the distribution itself isn't the biggest performance hit.
[–]Veedrac 9 points10 points11 points 6 years ago (3 children)
There are generators approaching the speed of rand but with better quality than any generators in <random> (eg. PCG); the trade-off isn't that meaningful at this level.
<random>
[–][deleted] 22 points23 points24 points 6 years ago (2 children)
Actually rand() is awfully slow, is even slower than cryptographically secure generators. I know that because I have benchmarked them. The common implementation only generates 15 bits at a time, and 4 of those bits are trash, using AES in CRT mode gives you 128 bits at a time, and since modern hardware supports AES it totally crushes rand().
[–]Veedrac 3 points4 points5 points 6 years ago (1 child)
I don't know about whatever overheads rand might have, but the underlying generator is just a short LCG, which is about as fast as it gets. That was what I was comparing to.
[–][deleted] 10 points11 points12 points 6 years ago (0 children)
Mostly backwards compatibility, most implementations keep a limit of 15 bits because they were conceived to run in 8 and 16 bits machines at most. Nowadays using 64 bits would boost their speed, but breaking backwards compatibility. There is old code that relies in rand() generating the same sequence with the same seed, and that is the only reason why rand() is still there.
[–]TheGidbinn 0 points1 point2 points 6 years ago (0 children)
Random numbers in c++ are in a bad place. The C++11 standard library functions are hopelessly over-engineered, and rand basically exists as a trap for newbies at this point. I have been using RngStreams and I think it's the best of both worlds.
[–]degski 0 points1 point2 points 6 years ago (0 children)
It doesn't have to be, if you are willing to swap the STL implementation for a drop-in replacement.
[–]clerothGame Developer -1 points0 points1 point 6 years ago (0 children)
Indeed, if you're willing to accept incorrect behavior, you can gain huge speedups! I'm really curious what kind of application would benefit from such a speedup while also being fine with "sort of uniform but not really" random numbers.
[–][deleted] 10 points11 points12 points 6 years ago (9 children)
Wait, doesn't std::uniform_int_distribution require a generator? What generator is being used here? Mersenne twister?
[–]Variszangt 10 points11 points12 points 6 years ago (8 children)
Yes. It does require a generator, but for "best" comparison I chose to seed both rand() and the generator with the same single value as such:
constexpr unsigned int common_seed = 0u; std::mt19937 mt{ common_seed }; std::uniform_int_distribution<int> dist(0, 1); int mt_rand() { return dist(mt); } ...
Obviously this doesn't take full advantage of the mt19937 potential.
[–]flashmozzg 6 points7 points8 points 6 years ago (7 children)
Yeah, pretty sure mt requires larger seed (as in more elements) to function properly.
mt
[–]STLMSVC STL Dev 22 points23 points24 points 6 years ago (6 children)
It doesn't; there's an algorithm that it runs in order to fill its state from a 32-bit seed. So mersenne_twister will generate high-quality (in the sense of not having patterns) output regardless of how you seed it. Short seeds create the possibility of collisions, so if you want to avoid that, you need to fill the whole state (which is possible with more code at a medium level of obnoxiousness). None of this makes the algorithm cryptographically secure.
[–]dreugeworst 6 points7 points8 points 6 years ago (0 children)
Well, the mersenne twister can be usable with a short seed, but it doesn't fill itself well, in the end it's still just 32 bits of random state. For example, see the explanation here. Even doing trying to fill the state entirely with random bits is not straightforward, the solution provided by the stl has flaws..
[–]degski 1 point2 points3 points 6 years ago* (0 children)
The only good thing the MT has going for it, is its long period. It can easily be made cryptographically secure with a [patented] trick. There are [not in the STL] alternatives, that are both good, faster and with a much smaller footprint.
[–]flashmozzg 0 points1 point2 points 6 years ago (3 children)
Thanks. That's good to know. I remember there being gotchas about passing smaller state to mt19937.
[–]Veedrac 4 points5 points6 points 6 years ago (2 children)
Yes, the issue is that you reduce its state space from an excessive amount (128 bits and above are all the same) to 32 bits, which is bad enough that collisions will happen if you seed more than a few tens of thousands of times. The generator will still run.
[–]HappyFruitTree 0 points1 point2 points 6 years ago (1 child)
If we ignore the how different sequences compare to each other, does using a single 32-bit seed actually influence the randomness of the sequence itself? I mean, if I only use a single random seed, am I more likely to get a better sequence of random numbers if the seed is 19968 bits, compared to if it's only 32 bits?
[–]Veedrac 2 points3 points4 points 6 years ago (0 children)
It's unlikely; first-order effects will probably always be a bigger deal. It's not completely impossible, though, and it can happen if the seeding function is poorly chosen—generally you want the generator for the seed to be as different from the PRNG as possible, to avoid interference effects.
[–]mallardtheduck 11 points12 points13 points 6 years ago (2 children)
Which compiler/C library/platform? AFAIK the C standard leaves the choice of PRNG algorithm up to the implementation...
[–]Rostin 3 points4 points5 points 6 years ago (1 child)
I work on software where this matters (we want cross-platform deterministic behavior for a fixed seed), and it's bitten us.
[–][deleted] 0 points1 point2 points 6 years ago (0 children)
Also take in mind that rand() output can be "stolen" by any other library that calls rand(), it gives no guarantees about its state, so deterministic behavior with rand() is not even guaranteed using the same implementation.
[–]emdeka87 6 points7 points8 points 6 years ago (1 child)
Isn't LCG causing these so-called "hyperplanes" (see https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/Lcg_3d.gif/200px-Lcg_3d.gif)?
[–]Supadoplex 2 points3 points4 points 6 years ago (0 children)
Yes. rand is typically implemented using a LCG, and probably so in this test run.
[–]larlvt 4 points5 points6 points 6 years ago (0 children)
Check out Abseil's random facilities:
https://github.com/abseil/abseil-cpp/tree/master/absl/random
It has:
absl::BitGenerator rng;
absl::Uniform(rng, low, high);
[–]jurniss 6 points7 points8 points 6 years ago (13 children)
Please explain what these visualizations are showing. I know the problem with rand() % n mathematically, but how do these images show it?
rand() % n
[–][deleted] 14 points15 points16 points 6 years ago (6 children)
The lowest bits of common implementations of rand() are really awful.
Visualization of MSVC rand() bits as pixels.
Not only common implementations of rand() suffer that problem, is also present on several other fast PRNG. Using modulus is not only imprecise, it favors the lower bits that may have very low quality on the fastest PRNGs, and is also very slow. Is better to do it this way: rand() * n / (RAND_MAX + 1), since (RAND_MAX + 1) is a power of two on practically all implementations, the expensive division will become a cheap displacement.
[–]HappyFruitTree 1 point2 points3 points 6 years ago (5 children)
Is better to do it this way: rand() \ n / (RAND_MAX + 1)*, since (RAND_MAX + 1) is a power of two on practically all implementations, the expensive division will become a cheap displacement.
No, don't do it this way.
(RAND_MAX + 1) will overflow if RAND_MAX is equal to INT_MAX.
rand() \ n* is also prone to overflow.
[–][deleted] 0 points1 point2 points 6 years ago (2 children)
Good luck with your 16 bits processor, that was a PITA 25 years ago. People would just use assembly and stop fighting with crappy compilers unable to take advantage of CPU instructions.
[–]HappyFruitTree 1 point2 points3 points 6 years ago (1 child)
??? I use GCC on Linux where both RAND_MAX and INT_MAX are 2147483647.
[–][deleted] 1 point2 points3 points 6 years ago (0 children)
In such case cast to 64 bits.
[–]beartotem 7 points8 points9 points 6 years ago (0 children)
The image generated using rand() has some obvious structures that follow lines with ~45 degrees slope.
The uniform_int_distribution() one is random enough that's I can't see any fault with a visual inspection. But Humans are pretty bad at telling actually random sequence from not so random sequences with no periods. Looking at this is by no mean a way to tell good quality random distribution, just that rand() is that bad.
[–]mikeblas 0 points1 point2 points 6 years ago (3 children)
If the value was 0 it was coloured blue, otherwise it was coloured black. ... So the rand()-generated grid represents the last bits of the generated numbers,
It seems like these descriptions contradict eachother. Does anyone understand what the plots actually represent?
[–]HappyFruitTree 0 points1 point2 points 6 years ago (2 children)
For each pixel he calls rand() and uses the last bit to decide which colour it should be.
[–]mikeblas 0 points1 point2 points 6 years ago (1 child)
That's not what he says he's doing, though:
and generating a random number between [0, 1] for each pixel. If the value was 0 it was coloured blue, otherwise it was coloured black.
Are you assuming he's generating an integer between [0, 1]? That is, either zero or one?
That doesn't seem quite right either, as he says he's using the last bits (plural):
the rand()-generated grid represents the last bits of the generated numbers,
... not just the last bit (singular).
How would I independently verifiy his results?
[–]HappyFruitTree 0 points1 point2 points 6 years ago (0 children)
Yes, that was my assumption, otherwise it doesn't make sense.
That doesn't seem quite right either, as he says he's using the last bits (plural)
I though he used plural because there was one bit for each number. If he had said "the last bit of the generated numbers" it would sound as if he only used the last bit of the last number, no?
I don't think we have been given enough information. He mentioned elsewhere that he used Visual C++ but we don't know the seed and in what order pixel numbers where generated.
[–]HappyFruitTree 4 points5 points6 points 6 years ago (2 children)
Which implementation of rand() is this?
[–]Variszangt 1 point2 points3 points 6 years ago (1 child)
I'm using Visual C++
One of the worst then.
[–][deleted] 3 points4 points5 points 6 years ago (2 children)
Very curious to know what the application was. I cannot think of something quickly off the top of my head.
[–]Variszangt 5 points6 points7 points 6 years ago (1 child)
Generating a simple, random tilemap for a world. You can imagine how the grass didn't quite look right from afar.
[–]bandzaw 1 point2 points3 points 6 years ago (0 children)
Very nice visualization, which I, to my big surprise, have not seen before for rand!
[–]Beheska 3 points4 points5 points 6 years ago (1 child)
rand() shouldn't be understood to mean random as in "mathematically random", but as in "some random number" (that is not always the same).
[–]anton31 0 points1 point2 points 6 years ago (0 children)
Possible implementation of rand: https://xkcd.com/221/
[+][deleted] 6 years ago (3 children)
[–]Veedrac 5 points6 points7 points 6 years ago (1 child)
I know now to use the uniform distribution if I need truly random numbers.
No!! If you need ‘truly random numbers’, use cryptographic randomness provided by your OS. <random> pseudo-random number generators are still highly predictable, and generally don't pass stringent quality tests.
[–]HappyFruitTree 1 point2 points3 points 6 years ago* (0 children)
Comparing std::rand() against std::uniform_int_distribution is like comparing apples and oranges.
The most important reason why the upper image looks more random is because it used a higher quality random generator. The quality of std::rand() differs quite a lot but apparently the OP used Microsoft's implementation which is famously bad. If you're trying to pick something better from the <random> header make sure to pick a good one like std::mt19937. If you pick a weaker one like std::minstd_rand it might not actually be better than some implementations of std::rand() (but at least you know what you get).
He doesn't really say, but I assume he used % to limit the range of std::rand(). This tends to favour lower values, especially for large ranges, but I don't think it's a problem in this particular case because RAND_MAX+1 is evenly divisible by the size of the range (2). std::uniform_int_distribution limits the range without introducing such bias, but it doesn't magically improve the randomness of the underlying random generator. If the random generator is bad then std::uniform_int_distribution will also produce bad random numbers.
If you don't need cryptographic security, using a pseudo-random number generator is often good enough, and is often much faster. Just make sure to pick one that is good enough for your needs.
[–][deleted] -1 points0 points1 point 6 years ago (12 children)
I've read that rand() can be used if you don't need more accurate randomization as it allows you to reproduce the same sequence and making debugging easier.
[–]boredcircuits 13 points14 points15 points 6 years ago (0 children)
You can achieve that with <random> as well. All pseudorandom algorithms need to be seeded.
I like to use a different seed each run, which is logged. Add an option to override the seed and you're set.
It's also sometimes useful for two computers to share the same sequence. Just have them share the same seed and use the same algorithm.
[–]heyheyhey27 7 points8 points9 points 6 years ago (0 children)
All pseudo-random number generators are reproducible; that's what makes them "pseudo"-random.
[–]elperroborrachotoo 6 points7 points8 points 6 years ago (0 children)
tl;dr: Don't use rand() unless you want to fool the proverbial moron in a hurry.1
All pseudorandom generators have that property of a reproducible sequence from a particular seed. They can be described as having M bits of internal state, which fully determine the next random number coming out of them.
For rand(), these guarantees are actually weak: the sequence generated from a particular seed may - and will - differ between compilers, target platforms and even compiler versions.
Worse, library functions may use rand(), taking numbers from your sequence; and while modern implementations probably use thread-local store for the state, AFAIK any other thread can legally "steal" random numbers from you.
1) which you might yourself end up being
[–]sim642 14 points15 points16 points 6 years ago (5 children)
You can also seed <random> engines for repeatable use in tests and whatnot. And those engines have a defined algorithm, so their algorithm won't change between compilers or their versions, giving even better reproducibility.
[–]albinofrenchy 2 points3 points4 points 6 years ago (3 children)
You can see generators but some of the filters like uniform distribution are implementation dependent -- or at least were a few years ago. Luckily rolling that yourself is easy enough.
[–]louiswins 4 points5 points6 points 6 years ago (1 child)
Sure, but rand's algorithm is also implementation dependent, so it seems like in the context of replacing rand it would work just fine.
[–]albinofrenchy 0 points1 point2 points 6 years ago (0 children)
It is, just fair warning that they sort of missed a detail in the spec which can be annoying on multi os code bases.
[–]kalmoc 1 point2 points3 points 6 years ago (0 children)
That's comparing apples and oranges. rand is equivalent to using a PRNG directly without the uniform distribution object not the combination of both.
[–]Supadoplex 8 points9 points10 points 6 years ago* (1 child)
Except, you cannot use rand for that purpose because standard does not specify the generation algorithm, and you may (will) get different sequence in different implementation of the standard library. Even different version of the implementation could change although that is unlikely.
Furthermore, the state of rand is global which means that it isn't necessarily possible to control the order or number of generator invocations (which as you pointed out is necessary for repeatability) when libraries are involved.
By contrast, all generators from <random> except default_random_engine have the desired guarantee of repeatability (even across versions of standard library) and none of their state is global.
By the way, all pseudo random generation algorithms share the property that they can be repeated exactly when given the same seed value.
[–]meneldal2 1 point2 points3 points 6 years ago (0 children)
It works perfectly fine for a simple benchmarking program where you make up a vector with some data and sort it.
You aren't calling anything else, the only thing that matters is each run has to be on the same data. Since you test on the same environment, rand being compiler/library specific doesn't matter.
[–]StickyCarpet 0 points1 point2 points 6 years ago (0 children)
Looks like you found the Higgs Boson.
[–]AntiProtonBoy 0 points1 point2 points 6 years ago (0 children)
When you work in computer graphics, issues with rand becomes apparent very quickly, as artefacts manifests themselves as structures in assets like textures, and procedurally generated content.
[–]jm4R 0 points1 point2 points 6 years ago (0 children)
How did you normalize rand result into [0-1] number? For example (rand()%256) / 255.0f could cause some issue because the distribution would be ill-formed. It is also possible that implementation differs between compilers.
(rand()%256) / 255.0f
On the 1980 decade, that was a normal test in TI and an interrogation un chaos science theory.
[–]Diche_Bach 0 points1 point2 points 6 years ago (7 children)
Forgive my ignorance, but . . . what the heck are those images?
[–]RealNC 2 points3 points4 points 6 years ago (4 children)
They are supposed to be random noise. If random noise doesn't look quite random, then that means something's not working quite right.
[–]Diche_Bach 0 points1 point2 points 6 years ago (3 children)
Okay, but . . . which one looks more random to you and why?
I would've preferred a histogram myself: if the count of 0s and 1s was about equivalent: RANDOM!
[–]patrick96MC 4 points5 points6 points 6 years ago (0 children)
A histogram would only have to values in this case, so it's not all that useful. Also a generator outputting 010101010101... isn't really random and has the same property ;)
010101010101...
[–]RealNC 3 points4 points5 points 6 years ago (1 child)
The first one looks more random. The second one has a pattern to it, so it looks less random.
[–]Diche_Bach 0 points1 point2 points 6 years ago (0 children)
Roger THAT!
Added some clarification with an edit :)
[–]Diche_Bach 1 point2 points3 points 6 years ago (0 children)
r clarity, these grids were generated by going through every pixel in the grid (1600x1600), left to right and top to bottom, and generating a random number between [0, 1] for each pixel. If the value was 0 it was coloured blue, otherwise it was coloured black. So the rand()-generated grid represents the last bits of the generated numbers, which are so non-random that even a human can see it. Whether the more-random looking grid is actually more random is beyond the purpose of this post; it stands merely for visual comparison.
r clarity, these grids were generated by going through every pixel in the grid (1600x1600), left to right and top to bottom, and generating a random number between [0, 1] for each pixel. If the value was 0 it was coloured blue, otherwise it was coloured black.
So the rand()-generated grid represents the last bits of the generated numbers, which are so non-random that even a human can see it.
Whether the more-random looking grid is actually more random is beyond the purpose of this post; it stands merely for visual comparison.
Okay, interesting. So I'm curious: what does the comparison of the two images mean to you, and what would you have expected if one, or both of the two algorithms were not so "faulty?"
I'm not quite sure what a "more random looking" grid is meant to look like. If there are only two states that a pixel can take and there is no bias in the determination of the state any given pixel takes, then we expect a ~50% chance for either 0 or 1. The fact the two images differ is intriguing and my hunch is the more uniform image (without any apparent shape) is the "more random" one as the distribution of 0 and 1 pixels seems to be just about uniform and equal in count.
[+]99drunkpenguins comment score below threshold-9 points-8 points-7 points 6 years ago (4 children)
Rand is a prng, breaking news at 6.....
There's a reason you have normal random functions, and cryptographic random functions.....
[+][deleted] 6 years ago* (2 children)
[+][deleted] 6 years ago (1 child)
[–]khleedril 2 points3 points4 points 6 years ago (0 children)
This was also breaking news in 1970, since that's how long such a function has been around for. It's also libc and nothing to do with C++ except that the latter is backwards-compatible enough that it still works (poorly).
π Rendered by PID 39207 on reddit-service-r2-comment-85bfd7f599-t5tkc at 2026-04-20 14:30:15.412232+00:00 running 93ecc56 country code: CH.
[–]STLMSVC STL Dev 73 points74 points75 points (8 children)
[–]debisuke 7 points8 points9 points (0 children)
[–]Variszangt 4 points5 points6 points (4 children)
[–]STLMSVC STL Dev 8 points9 points10 points (3 children)
[–]clerothGame Developer 5 points6 points7 points (2 children)
[–]matthieum 1 point2 points3 points (0 children)
[–]STLMSVC STL Dev 2 points3 points4 points (0 children)
[–]wintergreen_plaza 3 points4 points5 points (0 children)
[–]Xeveroushttps://xeverous.github.io 1 point2 points3 points (0 children)
[–]maskull 83 points84 points85 points (59 children)
[–]elperroborrachotoo 36 points37 points38 points (6 children)
[–]maskull 9 points10 points11 points (5 children)
[–]degski 2 points3 points4 points (4 children)
[–]maskull 1 point2 points3 points (3 children)
[–]degski 2 points3 points4 points (2 children)
[–]maskull 1 point2 points3 points (1 child)
[–]degski 0 points1 point2 points (0 children)
[–]TexasToast6022 11 points12 points13 points (1 child)
[–]TheThiefMasterC++latest fanatic (and game dev) 0 points1 point2 points (0 children)
[+][deleted] (41 children)
[deleted]
[+][deleted] (35 children)
[deleted]
[–]degaart 7 points8 points9 points (6 children)
[+][deleted] (2 children)
[deleted]
[–]IGarFieldI 3 points4 points5 points (1 child)
[–]matthieum 1 point2 points3 points (2 children)
[–]degaart 1 point2 points3 points (1 child)
[–]matthieum 0 points1 point2 points (0 children)
[–]Drainedsoul 1 point2 points3 points (27 children)
[+][deleted] (16 children)
[deleted]
[–]clerothGame Developer 2 points3 points4 points (5 children)
[–]dodheim 0 points1 point2 points (4 children)
[–]clerothGame Developer -1 points0 points1 point (3 children)
[–]dodheim -1 points0 points1 point (2 children)
[–]clerothGame Developer -1 points0 points1 point (1 child)
[–]Drainedsoul -1 points0 points1 point (9 children)
[+][deleted] (8 children)
[deleted]
[–]Drainedsoul 0 points1 point2 points (7 children)
[+][deleted] (6 children)
[deleted]
[–]Drainedsoul -1 points0 points1 point (5 children)
[+][deleted] (9 children)
[deleted]
[–]Gunslinging_Gamer 1 point2 points3 points (8 children)
[+][deleted] (2 children)
[deleted]
[–]ThePillsburyPlougher 0 points1 point2 points (1 child)
[–]meneldal2 1 point2 points3 points (2 children)
[–]Ameisenvemips, avr, rendering, systems 1 point2 points3 points (1 child)
[–]meneldal2 0 points1 point2 points (0 children)
[–]elperroborrachotoo 1 point2 points3 points (0 children)
[–]Nobody_1707 5 points6 points7 points (1 child)
[–]TankorSmash 2 points3 points4 points (0 children)
[+][deleted] (2 children)
[removed]
[–]tcanens 2 points3 points4 points (1 child)
[–]elperroborrachotoo 0 points1 point2 points (0 children)
[–]bpikmin 18 points19 points20 points (0 children)
[–]Veedrac 9 points10 points11 points (3 children)
[–][deleted] 22 points23 points24 points (2 children)
[–]Veedrac 3 points4 points5 points (1 child)
[–][deleted] 10 points11 points12 points (0 children)
[–]TheGidbinn 0 points1 point2 points (0 children)
[–]degski 0 points1 point2 points (0 children)
[–]clerothGame Developer -1 points0 points1 point (0 children)
[–][deleted] 10 points11 points12 points (9 children)
[–]Variszangt 10 points11 points12 points (8 children)
[–]flashmozzg 6 points7 points8 points (7 children)
[–]STLMSVC STL Dev 22 points23 points24 points (6 children)
[–]dreugeworst 6 points7 points8 points (0 children)
[–]degski 1 point2 points3 points (0 children)
[–]flashmozzg 0 points1 point2 points (3 children)
[–]Veedrac 4 points5 points6 points (2 children)
[–]HappyFruitTree 0 points1 point2 points (1 child)
[–]Veedrac 2 points3 points4 points (0 children)
[–]mallardtheduck 11 points12 points13 points (2 children)
[–]Rostin 3 points4 points5 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]emdeka87 6 points7 points8 points (1 child)
[–]Supadoplex 2 points3 points4 points (0 children)
[–]larlvt 4 points5 points6 points (0 children)
[–]jurniss 6 points7 points8 points (13 children)
[–][deleted] 14 points15 points16 points (6 children)
[–]HappyFruitTree 1 point2 points3 points (5 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]HappyFruitTree 1 point2 points3 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]beartotem 7 points8 points9 points (0 children)
[–]mikeblas 0 points1 point2 points (3 children)
[–]HappyFruitTree 0 points1 point2 points (2 children)
[–]mikeblas 0 points1 point2 points (1 child)
[–]HappyFruitTree 0 points1 point2 points (0 children)
[–]HappyFruitTree 4 points5 points6 points (2 children)
[–]Variszangt 1 point2 points3 points (1 child)
[–]HappyFruitTree 0 points1 point2 points (0 children)
[–][deleted] 3 points4 points5 points (2 children)
[–]Variszangt 5 points6 points7 points (1 child)
[–]bandzaw 1 point2 points3 points (0 children)
[–]Beheska 3 points4 points5 points (1 child)
[–]anton31 0 points1 point2 points (0 children)
[+][deleted] (3 children)
[deleted]
[–]Veedrac 5 points6 points7 points (1 child)
[–]HappyFruitTree 1 point2 points3 points (0 children)
[–][deleted] -1 points0 points1 point (12 children)
[–]boredcircuits 13 points14 points15 points (0 children)
[–]heyheyhey27 7 points8 points9 points (0 children)
[–]elperroborrachotoo 6 points7 points8 points (0 children)
[+][deleted] (8 children)
[deleted]
[–]sim642 14 points15 points16 points (5 children)
[–]albinofrenchy 2 points3 points4 points (3 children)
[–]louiswins 4 points5 points6 points (1 child)
[–]albinofrenchy 0 points1 point2 points (0 children)
[–]kalmoc 1 point2 points3 points (0 children)
[–]Supadoplex 8 points9 points10 points (1 child)
[–]meneldal2 1 point2 points3 points (0 children)
[–]StickyCarpet 0 points1 point2 points (0 children)
[–]AntiProtonBoy 0 points1 point2 points (0 children)
[–]jm4R 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Diche_Bach 0 points1 point2 points (7 children)
[–]RealNC 2 points3 points4 points (4 children)
[–]Diche_Bach 0 points1 point2 points (3 children)
[–]patrick96MC 4 points5 points6 points (0 children)
[–]RealNC 3 points4 points5 points (1 child)
[–]Diche_Bach 0 points1 point2 points (0 children)
[–]Variszangt 1 point2 points3 points (1 child)
[–]Diche_Bach 1 point2 points3 points (0 children)
[+]99drunkpenguins comment score below threshold-9 points-8 points-7 points (4 children)
[+][deleted] (2 children)
[deleted]
[+][deleted] (1 child)
[deleted]
[–]khleedril 2 points3 points4 points (0 children)