• Forum
  • Lounge
  • I know someone who would really like con

 
I know someone who would really like constexpr right now...

closed account (E0p9LyTq)
I know someone who would really like constexpr right now...

Similar level of cognitive disconnect surrounding the level of usability between srand/rand and the C++ <random>/<chrono> libraries.

</rant> :)
It's a shame C++ is so deeply hated by some specific people that they won't even allow any use of it, let alone use of the good parts.
closed account (E0p9LyTq)
https://lwn.net/Articles/749064/

This max() mess is driven by problems with fixes working with newer compilers, and being vomited up with older ones.

Ah, the ideal world of portability, trashed when the real world rears its ugly head.
VLAs really are just a dumb idea under the best of circumstances. In the kernel it's just braindead.
What I don't understand is, if they're really serious about getting rid of VLAs, why they don't just ask the GCC guys to put in a flag that disables them and errors if it finds any (maybe GCC already has such a flag, I don't know). The old "compiler as a static analysis tool" trick.
closed account (E0p9LyTq)
It's a shame C++ is so deeply hated by some specific people that they won't even allow any use of it, let alone use of the good parts.

http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/

Reading this article/rant many, many months ago I ran across this:

The C random library has always been… to put it politely… less than ideal. Okay, it’s pretty fucking horrible. It’s so bad that the C standard itself suggests you’d be better off not using it.[1]

At this point there is always a horde of people who will jump up and protest – the usual suspects, who continue to cling to long obsoleted and dangerous constructs just because that was what they first learned, and they refuse to learn the better, modern constructs that will make their code much more robust and extensible. “It’s good enough!” they will cry. “It’s good enough for simple uses.”

I know I have run across that attitude here when I have suggested someone look at how C++ can be used to generate pseudo-random numbers, instead of relying on srand/rand.
closed account (E0p9LyTq)
@helios,

Just a few moments ago I smacked a spam post with a title remarkably similar to yours.

The spammers are trying to be devious. Heh.
http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/
I don't agree with several of the points raised in that post.

rand() has a very limited range.
Totally irrelevant when you can call rand() three times and assemble a uint32_t that way.

Nothing about rand()‘s behaviour is required.
Interesting way of arguing. Mention first what it actually does (have a small range) and then what it might do. Somewhere. Maybe. Please don't ask for examples.

You’re probably seeding it wrong.
Actually, you're probably not seeding it wrong. If someone is using rand() because they don't know any better, how likely is it that their code will start more often than once per second?

You’re probably converting it to a range wrong.
Bias is such a dumb argument. If we take the very common MAX_RAND == 32767 and you try to modulo the output of rand() to the range, say, [0; 42), the probabilities of the values in the range [0; 7) will be approximately 1/780 higher than those of those in the range [7; 42). Granted, the bias does get worse the larger the divisor, with % (MAX_RAND - 1) being the worst possible case, causing 0 to be twice as likely as any one of the other values. In absolute terms, though, the probability of 0 turns out to be 0.0061% instead of 0.003%.

I know I have run across that attitude here when I have suggested someone look at how C++ can be used to generate pseudo-random numbers, instead of relying on srand/rand.
<random> is garbage. I'll roll my own xorshift and seed it with std::random_device sooner than I'll use those std::mt19937 and std::uniform_distribution abominations.
It's like <iomanip> all over again. Let's take something that's intuitive and easy to use, if a little broken, and "improve" it until it's so cumbersome that people start rolling their own implementations just to avoid using it.

Whether these issues with rand() are actually problems or not again depends on what you're using rand() for. If you're doing Monte Carlo or cryptography and you're using rand() then sure, I'll agree that there's something wrong with you. For other situations, it's much less clear.

If you want an example where having a weak PRNG can be good, Google "rng hacking". Long story short, old consoles weren't very good at generating random numbers because they couldn't seed generators with unique values, so games that needed randomness used other tricks to get entropy, such how long it took you to push start on the title screen. In the particular case of Pokemon Red, the game continually gets entropy from all the buttons. A normal player will just go about their business and not even realize what's going on, but a clever player can abuse the PRNG to get better numbers for themselves. It adds an entirely new layer of complexity to the gameplay.
@helios can you explain or link to an explanation for why you don't like the <random> standard library? It's been pretty painless in my experience.
"Painful" isn't the word I'd use, "annoying" is. Same for the <iomanip> stuff.

Just look at how any other PRNG class interface looks like. Who ever heard of having to create a new distribution object every time you need to generate a new number (I know that's not necessarily the case, but it is if your range is variable)?
Was this so much to ask for?
1
2
3
4
5
6
7
std::random rng; //Seed by default from std::random_device. Also, not need to remember the number 19937! Hooray!
rng.get(); //Get 32 random bits
rng.get(n); //Get a random number in the range [0; n)
rng.get(a, b); //Get a random number in the range [a; b]
rng.get_double(); //Get a random double in the range [0; 1)
char array[32];
rng.random_buffer(array, 32); //Randomize a void *. 

I have nothing against an interface that doesn't hide anything from you, but good libraries also give you an easy interface with the most common functionality and sensible defaults, because the designers realize that most of the time you won't need to fine-tune that stuff. The first example that comes to mind is libcurl; another is zlib.
For such a basic function as random number generation, <random> is shockingly bad. It's not like there aren't thousands of examples from other languages to choose from.

EDIT: <iomanip> has the exact same problem. Let's take one of the common problems you can find:
A: How do I print a hex number with leading zeroes in C++?
B: Oh, you just do
1
2
3
4
5
stream << "0x"
    << std::hex //this goes away after the first datum
    << std::setw(8) //this doesn't
    << std::setfill('0') //neither does this
    << your_number;

A: ... What if I don't mind using sprintf()?
B: Then just do sprintf(array, "0x%08X", your_number);

It's just ridiculous. It's like some of the people in the standard committee hate programmers.
Last edited on
helios wrote:
it's so cumbersome that people start rolling their own implementations just to avoid using it.

That's why library fundamentals TS v2 has randint()

1
2
3
4
5
6
7
8
#include <iostream>
#include <experimental/random>
 
int main()
{
    int random_number = std::experimental::randint(100, 999);
    std::cout << "random 3-digit number: " << random_number << '\n';
}

demo https://wandbox.org/permlink/q5AtzINSJD5qzodQ
Well, that's better, but not having a class means a) you give up control over the sequence, and b) either there's some synchronization to maintain thread safety, or there's no thread safety.
randint's engine is a thread-local instance of std::default_random_engine (filtered through std::uniform_int_distribution) and it has a reseed() function to seed it with a known value (default seed is unspecified). No other controls, though: if you need another PRNG, gotta use the C++11 library.
Last edited on
It's like some of the people in the standard committee hate programmers.

I don't think that they hate someone. My guess is that they are academics who don't use their creation to write any real code.
randint's engine is a thread-local instance of std::default_random_engine (filtered through std::uniform_int_distribution) and it has a reseed() function to seed it with a known value (default seed is unspecified). No other controls, though: if you need another PRNG, gotta use the C++11 library.
I'm not talking about the specific PRNG algorithm, what I mean is that you can't have separate sequences advancing independently from each other like you can with std::mt19937. It's basically global state, so the numbers being generated by unrelated code affect the numbers you generate too.
@helios I completely agree with your opinion on the ancient iostreams library, but the random library seems fine to me. I don't see anything in your complaints about random that annoys me. It's pretty trivial to wrap it to your proposed interface, and there are typedefs with sensible defaults. Also I was under the impression the iostreams library was designed well before a committee was involved, they have to live with past mistakes - do I have my history out of order here?
You can always patch things up with more code. Saying "it can be wrapped by another interface" conveys no information. I could also just not bother with it and use a better-designed PRNG class (which I do).
Random number generation is such a basic feature of a language that there should be no need to wrap anything. The default interface should be sensible.
Incidentally, I'm not alone in thinking <random> sucks, although different people cite different reasons: http://www.cplusplus.com/forum/lounge/221672/

Also I was under the impression the iostreams library was designed well before a committee was involved
It doesn't matter when it was designed, what matters is that at some point the standardization committee looked at <iomanip> (however it looked like back then. That was somewhat before my time) and included it in C++98 in its current form. No, there's no reason why they couldn't have made changes at that point. They made more fundamental changes to the language, like for scoping rules.
I agree, the random interface could be better. If you want to have a dynamic bound, you need to have a new object each time, which just seems like a total waste, and just annoying to use. That being said, I don't often need constantly changing bounds, but it's still clunky to use compared to C# or Java.
Topic archived. No new replies allowed.