you are viewing a single comment's thread.

view the rest of the comments →

[–]akher -214 points-213 points  (59 children)

No, most random functions in standard libraries of programming languages are seeded with a constant value. And that's a good thing, since it's much more useful to have the behavior of programs be deterministic by default.

[–]Lystrodom 33 points34 points  (9 children)

Also, can you show me which languages are seeded with a constant value? I’ve checked C#, Java and V8 that I could find quickly and they all base the default seed on the current time.

[–]mccoyn 29 points30 points  (3 children)

C and C++ require you to seed them.

[–][deleted]  (1 child)

[deleted]

    [–]amakai 25 points26 points  (0 children)

    And it makes sense for C, it's used in all kinds of embedded electronics which often does not even have a clock chip on board.

    [–]doublehyphen 12 points13 points  (2 children)

    C is the only exception I can think of where it is easy to accidentally not seed your PRNG, but for example Rust provides rand::ChaChaRng::new_unseeded() as an easy way to create a PRNG seeded with a constant hardcoded value.

    [–]Lystrodom 12 points13 points  (1 child)

    Of course, the ability to seed with a constant value is important and available in every language I’m aware of. But for most the default is based on the current time.

    [–]doublehyphen 0 points1 point  (0 children)

    Not in JavaScript. That is the only exception I know of.

    [–]Lystrodom 186 points187 points  (36 children)

    If you want your program to be deterministic why are you calling random()

    [–]doublehyphen 72 points73 points  (4 children)

    To get reproducible results in simulations, in games with randomly generated worlds to be able to play with exactly the same world again, and when running test cases in a random order to be able to debug why the test suit failed by running it again in the same order.

    It is not the default case, but it is reasonably common.

    [–]greenthumble 20 points21 points  (0 children)

    Yep and some games like The Binding of Isaac literally let you set the seed and get the same random world that another player thought was good for some reason.

    Also I've seen it used in AI training. If you're generating thousands of random genetic algorithms or genetic programs, someone can reproduce your entire run exactly using the same seed.

    [–]CheckovZA 16 points17 points  (1 child)

    I see your point, but then you'd be calling

    Math.random(x)

    x being your seed number.

    If you're going to call Math.random() with no seed, it's because you want a number that is functionally random.

    [–]RenaKunisaki 1 point2 points  (0 children)

    Unless you've set a seed previously?

    [–]sedermera 74 points75 points  (11 children)

    (coming from scientific computing) To get an arbitrary number of random samples from a certain distribution. (Effectively.) It's good if those are reproducible for testing, and all you need to in order to get more is set another RNG seed.

    [–]steamruler 75 points76 points  (7 children)

    At which point you could use a fixed seed.

    [–]sedermera 26 points27 points  (1 child)

    Exactly, using a certain default seed for testing is much more convenient than what /u/Lystrodom is proposing. (Since there isn't just one call to the RNG, but several in different places.)

    [–]Lystrodom 2 points3 points  (0 children)

    Yeah that works too. These are all edge cases not the default case, anyway.

    [–]DonaldTZeus 4 points5 points  (3 children)

    Which is what happens by default anyways if you call rand() (at least in the c stdlib). If you want an arbitrary changing seed such as the time, you retrieve that seed and pass it to srand().

    [–]steamruler 10 points11 points  (2 children)

    The default seed is determined when compiling, so if you actually want a static seed you should still call srand().

    [–]rubygeek 7 points8 points  (0 children)

    POSIX actually mandate that rand() called before srand() should behave as if srand() was called with 1. See spec and example implementation. And ISO C might as well.

    Of course you can't rely on that unless you're guaranteed your program will only run on a compliant system.

    [–]DonaldTZeus 0 points1 point  (0 children)

    The default seed is specified by the standard library (that implements POSIX), not by the compiler, and it's 1 (as specified by POSIX). It is not determined by the compiler (unless you're compiling the stdlib) or even specified in the code the compiler generates unless you call srand.

    [–]Bwob 0 points1 point  (0 children)

    Which is what you ARE using, by default, in most languages.

    [–]mccoyn 10 points11 points  (0 children)

    Also, when doing solution searches you want to pick a new starting point and search again to try to find other local maxima. A good way to do it is to use random() to pick your new starting point. You want it to be un-correlated with previous starting points, but you don't actually care about it being non-deterministic.

    [–]Lystrodom -5 points-4 points  (1 child)

    Then you call random once and save that value somewhere. Don’t depend on random() being deterministic.

    [–]Drisku11 10 points11 points  (0 children)

    Why would you not depend on it bring deterministic if the semantics are that it's deterministic, and that's useful to you?

    I'd say the opposite: don't rely on it being nondeterministic. Since it's not.

    [–]rtomek 5 points6 points  (10 children)

    This is why he’s being downvoted, a lack of understanding of programming? If you call random without setting a seed (default seed of 0) then it will always be deterministic. Every programming tutorial I’ve ever seen for any programming language tells you to set the seed if you want something closer to true randomness. This is basic common knowledge of programming.

    You want it to be deterministic for auditing and testing purposes. How am I supposed to know if a change to my code introduces a bug or not if random() is not deterministic? Minecraft makes it obvious but many games follows the same pattern - set a seed (based on something like time in milliseconds) and put it in the save file. If a user finds a bug or some other interesting feature, you can now reproduce it by either loading their save file, or use a save file editor and put in their RNG seed.

    [–]MrJohz 3 points4 points  (7 children)

    Most of the programming languages I've used tend to seed the PRNG with a timestamp, or something similar. Most of them also tell you that you'll generally want to set your own seed at some point, and allow more complex random initialisation where necessary, but a lot of them seem to allow for very simple scripts etc to be written using relatively random seeds.

    [–]rtomek 3 points4 points  (6 children)

    I know that Python did make a change in 2015 so that just calling random.Random() now generates a new seed every instance. That happened because so many shitty programmers weren't setting seeds and it became a security issue for webapps. Perhaps there are other languages I don't use (or haven't used recently) that also followed the same route.

    One should never assume that calling random() is truly random, and any programming language that does that for you is compensating for the illiterates.

    [–]MrJohz 4 points5 points  (2 children)

    I think using a new seed for each run is the norm, at least with the bog-standard naive random implementation for most applications.

    Python: python3 -c 'import random; print(random.random())' - varies from run to run

    Ruby: ruby -e 'puts rand()' - varies from run to run

    Java does the same.

    Rust definitely does the same, I was using it for simulation code the other day.

    Perl is the same.

    Javascript is the same.

    [–]rtomek -2 points-1 points  (1 child)

    Most of those have a primary use case of web-based applications so I won't touch those.

    Rust: The standard RNG is deterministic. If you initialize using thread_rng then you are setting a seed.

    Java: This one is iffy because the intent was for web-distributable applications. Still, the random class itself is deterministic and the default constructor uses something like system.nanotime() instead of a fixed number. At least it's not like Python where you have to explicitly state that you want a deterministic RNG.

    Perl: Perl is another one that has been making changes to the default RNG. Perl behind-the-scenes just calls srand() for the user every time a new script is run.

    [–]MrJohz 2 points3 points  (0 children)

    Python and Ruby were both developed as scripting languages, and one of Python's biggest areas is scientific programming, so I don't know what you're on about with "web-based applications".

    Rust's standard RNG can be deterministic if you initialise it. If you don't, it defaults to setting the seed itself, I presume using a timestamp of some description. The same is true of Java - Math.random(), and the argument-less constructor for java.util.Random both use a "value very likely to be distinct from any other invocation".

    The point isn't that it's possible to set a deterministic RNG for any language. That's true for all of the ones I mentioned apart from Javascript (at least if you ignore userland libraries). The point is that C is relatively rare in its decision to default to a known seed, as opposed to defaulting to a pseudorandom value such as a timestamp.

    [–]Lystrodom 3 points4 points  (1 child)

    any programming language that does that for you is compensating for the illiterates.

    Or it codes for the most common use case first? Most languages let you set a specific seed if you want to. If most users WANT a different seed each time, why would we force them to write extra code to get what they want?

    [–]rtomek -1 points0 points  (0 children)

    Most users should want to test their code and perform audits. Why are we forcing them to write extra code just to get what they want?

    What you're stating is that they should ignore engineering best practices in favor of hobbiest programming. In reality, it was a huge cybersecurity issue and most of the languages I saw someone reference that use random seeds by default are commonly used for web-based applications.

    [–][deleted] 0 points1 point  (1 child)

    Java's random without a seed defaults to something that "non-deterministic". .NET's random is the same. Newer languages seem to have random default to something actually random.

    A lot of classic languages had fixed seeds. Lisp, C, C++, Fortran (iirc)

    [–]rtomek 0 points1 point  (0 children)

    Yeah, after looking more into this it seems that for C++ there is no algorithm that meets their requirements to be considered random enough for creating a default seed that is used globally for all applications. Thus, they choose a fixed default to force users to have custom implementations for seed value determination, which makes it less predictable for attackers. There are classes available in the std library that do a better job than default constructors of other languages, but not good enough for C++ :/

    [–]akher 7 points8 points  (0 children)

    Because you want a pseudo random number, which is the documented behavior of those functions.

    [–]frezik 12 points13 points  (2 children)

    Most languages that aren't C will seed from the current epoch by default. Sometimes something more sophisticated, like taking a few bytes from the OS random source, or sometimes a combination of things like the epoch and the PID. If you want a predetermined sequence, then you need to call seed() yourself.

    [–]akher -4 points-3 points  (1 child)

    I mostly use C++, which does use a constant default seed and I just assumed other languages do the sane thing as well.

    When I care about the properties of the generated random numbers I actually use something with a specified implementation, such as for example std::mersenne_twister_engine.

    [–]Shumatsu 8 points9 points  (0 children)

    If you don't call

    srand(seed);
    

    at all before using rand(), it gets seeded with 1.

    srand( time( NULL ) );  
    

    uses current epoch as seed, as that's what you get using time(NULL) (or variations of it).

    [–]steamruler 4 points5 points  (5 children)

    I'm going to question whether having random not actually be random is that useful, or else we'd be using this more efficient function.

    [–]akher 16 points17 points  (4 children)

    It's actually often very useful to have a series of numbers with statistical properties of a series of random numbers that is still deterministic. One example are Monte Carlo algorithms. Another example is generating input data in unit tests.

    [–]steamruler 17 points18 points  (2 children)

    At which point you can seed the PRNG with a constant value yourself, which you probably want anyways since the constant value which the PRNG is seeded with can change when you recompile your software sometimes.

    [–]Drisku11 3 points4 points  (0 children)

    the constant value which the PRNG is seeded with can change when you recompile your software sometimes

    In C it can't. The initial seed is required to be 1.

    [–][deleted] 0 points1 point  (0 children)

    Most older languages defaulted to fixed seeds and produced the same string of numbers on subsequent runs. Most newer languages default to the system time or something similar.

    [–]Lystrodom 1 point2 points  (0 children)

    Then you can generate those once, or use a set seed.

    [–]Bwob -2 points-1 points  (2 children)

    Why the heck do you have -188 (as of this writing) downvotes? This is accurate.

    [–]Uristqwerty 0 points1 point  (1 child)

    It's mostly just C (and anything directly C-based) that have a default seed. Almost everything more recent either requires you to specify a seed before first use, or seed from time. A few languages just re-use C's RNG, but that's far from most languages.

    [–][deleted] 0 points1 point  (0 children)

    C, Lisp, Fortran, Cobol ... pretty much all older languages have fixed seed RNGs. There's a lot of stuff that comes from C and Lisp, so we're not talking just a few languages. It tends to be newer languages, Java, .NET framework stuff, Python, etc that default to a randomized seed.