Just take numbers from Australian quantum computer on giant cloud and transport inside each of the player's individiual compiler using processor power before he begins installing the game.... so that wayw everyone has different worlds in their game that are randomized only for themselves. Or use rand, maybe... it's also good.
this doesn't contradict the 2^32 repeating pattern if you ever wrote a pseudo-random number generator, it returns a truncated value derived from the actual held seed.
@@dimanarinull9122 It may repeat after 2^32 times, but if you want a number bigger than 32767 you would have to call rand() multiple times and that would be less random and far slower than using mt19937 or other algorithms. The only reason you would use rand() is if you are using C, or if you are experimenting and don't need true randomness, precision, or speed.
I abandoned rand when I was moving a bunch of agents on screen in a random direction and they all almost immediately ended up on the left edge of the screen. Every time. Switched to Mersenne Twister, best I could find back then.
7:14 Weird complaint to make since rand is even more implementation defined than the distributions in If you read the C++ standard, it requires the implementation of distributions to follow a specific math formulas, so the only difference from platform to platform possible is performance and floating point errors (but rand can't even do floats) But if you read the C standard, you'll see that rand's implementation is defined as a "function that generates a sequence of pseudo-random integers from 0 to RAND_MAX", so rand can be any function that generates numbers and you are much more likely to see difference from platform to platform because standard imposes no restrictions on how numbers are generated.
Bro did you also read the C++17 standard. I am crying I found someone who is just as insane as me. You are so right and I wanted to comment the exact same thing. The quality of rand depends on the compiler developer whether its fast slow good or bad. I will probably implement some sort of xor shift for the rand() function but I will see.
rand()'s artefacts in the msvc implementation are able to be seen at a non-trivial scale. for example, if you make a world with blocks placed based on something like rand() % 9 == 0, it'll repeat noticeably often in different places. that and the global state issue means that I probably wouldn’t use it for anything permanent as faster and more uniform random number generators than what is typically implemented for rand() exist
rand() is also quite slow. I was using a xoshiro256++ algorithm, and it was 4(O0) to 10(O3) times faster, while also having full 64bit range and decent uniformity.
I use pcg random - tiny code, high quality, 32-bits per output (not 15-bits like rand() ), easy to create multiple instances. No "let's think for a bit" reload cost like Mersenne Twister. It's a winner IMHO
Came to say this, pcg is my go-to. Also, there are different versions with larger states (eg, for simulations, where you might want to walk many billions steps and it's good practice to use only a fraction of the state), and they're still really simple and pretty quick.
I think it's also worth mentioning that by limiting the range of numbers using the modulo operator for non-powers of 2, you're biasing the lower end of the range of numbers slightly. You should to a long multiply and shift for unbiased ranges.
eh that's the last of the problems, its like the bias will be after 2^32 numbers lol. The real problem is the fact that the lower bits are way worse than the high bits of the output of rand, (you can try that yourself, if you generate a texture using the lowest bit of rand result the result is bad, but if you use the most significant bit you get a very very good quality noise
@ true, but the math pedant in me wants the most "correct" interpretation of the raw result haha, larger ranges might produce more noticeable bias with MSVC's impl only generating numbers up to 32767 too. But ideally you have some better source of random numbers anyway than an LCG.
About copying random number engines: IIRC you're supposed to initialize it once in your project (or at least as few times as possible) and share it between the functions that need to pull random numbers. About random_device: On GCC before version 9.2 it was deterministic.
I looked up some prng values from wikipedia and made my own "random library" that is shitty but is good enough for most applications and is not repeating. a good way to have a decent uniform distribution is to do the extra few operations required to normalize the output over the range of numbers: int random(int out_mul) {return (int)(out_mul * (rand() / (float)RAND_MAX));} // preventing integer overflow due to multiplication is generally better for creating less artifacts in the rand output. replace the rand() and RAND_MAX values with the ones from your implementation and you have a decent random function for any number, even if it's a bit more time intensive than a single modulus with its double conversions and a division. the time loss on that shouldn't be that critical for most applications and can have the operation reversed to remove the need for conversions if you can guarantee no overflow happens, just like you could reduce the need for modulus with bitwise operations in cases where those cause actual slowdown of the process(had that exact issue before)
If you're coming from rand() without using a random srand(), you should initialize your mt19937 without a random seed too. Just use the constructor without arguments
Did you know that the C++ standard doesn’t require that std::random_device (the pure random number generator) generates purely random numbers? So instead of just requiring that hardware without pure random byte generation instructions don’t support it random_device (which would be sensible and expected behaviour), it insists that they use a PRNG fallback instead. IDK if it MinGW GCC still does this, but for a few years it would always generate the same sequence of numbers the first time it was called, making it useless for seeding other pRNGs even if you ignored the fact that its numbers aren’t big enough for a full mt19937 seed.
cpp fail moment. Ok sure hardware that doesn't have pure random numbers should just fall back to somethinf different, but what excuse did mingw have :))) at least use some time or some os api function idk
@@lowlevelgamedev9330 I assume the reason for it is to signal to the user that the implementation is using PRNG instead of true RNG but at the same time I think the standard would be better if they forced random_device to throw an exception or compile error/warning when built for hardware without an appropriate hardware instruction. At least then you could expect consistent and “portable” (for lack of a better word) behaviour. I don’t think there should really be any situation where a generator that’s explicitly for pure randomness has a hidden, implementation-defined pseudorandom fallback behaviour.
C++ hasn't been fun to code since C++14 for me, after almost 20 years with C++ I just gave up on it. Horrible new features that over complicate things and bizarre new syntax like initializers instead of assignments, no default networking library. I don't know what's new anymore but when I was using C++, there was no true unicode support (not the garbage semi implementation currently) for the string library. I used to find myself spending a great deal of time configuring mundane property sheets for visual studio for the different libraries and linker problems, that has nothing to do with programming at all, very boring stuff. And importing and compiling external libraries is a pain in the neck.
@@rnts08 Agree, but I really like the concept of objects and polymorphism. I am not sure about Objective-C (Obj-C) since I never used it (probably because it was owned by Apple), but since that one is defunct, I would prefer a similar one.
I have a video on it but like just use cpp with the things that you want to use from it. I for example don't ever write destructors but I use pre made classes like vector and others
@@lowlevelgamedev9330 I will check it out, thanks. But still, importing libraries and compiling them is a nightmare, I used to juggle 2 or 3 big libraries like wxWidgets, and SDL and few others at the same time. Thinking about the past gives me shivers 😱 Just glancing at new C++23, they seem to have "import" Modules now, not really sure if it is widely adopted though.
Just take numbers from Australian quantum computer on giant cloud and transport inside each of the player's individiual compiler using processor power before he begins installing the game.... so that wayw everyone has different worlds in their game that are randomized only for themselves. Or use rand, maybe... it's also good.
yeah exactly 😂
MSVC's rand() only goes up to 32,767
This is funny, it makes ZX Spectrum RND (1982 computer, 16/48K RAM) twice as good :D
@@SianaGearz maybe, but it is also possible that the distribution is worse in other senses
@@user-sl6gn1ss8p from what i remember it's actually fairly well behaved. But it's not trying to be fast at only a handful statements per second.
this doesn't contradict the 2^32 repeating pattern if you ever wrote a pseudo-random number generator, it returns a truncated value derived from the actual held seed.
@@dimanarinull9122 It may repeat after 2^32 times, but if you want a number bigger than 32767 you would have to call rand() multiple times and that would be less random and far slower than using mt19937 or other algorithms. The only reason you would use rand() is if you are using C, or if you are experimenting and don't need true randomness, precision, or speed.
I abandoned rand when I was moving a bunch of agents on screen in a random direction and they all almost immediately ended up on the left edge of the screen. Every time. Switched to Mersenne Twister, best I could find back then.
7:14 Weird complaint to make since rand is even more implementation defined than the distributions in
If you read the C++ standard, it requires the implementation of distributions to follow a specific math formulas, so the only difference from platform to platform possible is performance and floating point errors (but rand can't even do floats)
But if you read the C standard, you'll see that rand's implementation is defined as a "function that generates a sequence of pseudo-random integers from 0 to RAND_MAX", so rand can be any function that generates numbers and you are much more likely to see difference from platform to platform because standard imposes no restrictions on how numbers are generated.
Bro did you also read the C++17 standard. I am crying I found someone who is just as insane as me. You are so right and I wanted to comment the exact same thing. The quality of rand depends on the compiler developer whether its fast slow good or bad. I will probably implement some sort of xor shift for the rand() function but I will see.
rand()'s artefacts in the msvc implementation are able to be seen at a non-trivial scale. for example, if you make a world with blocks placed based on something like rand() % 9 == 0, it'll repeat noticeably often in different places. that and the global state issue means that I probably wouldn’t use it for anything permanent as faster and more uniform random number generators than what is typically implemented for rand() exist
You're right but he did say that first half multiple times already.
5:05 You listed so many cons here already that you might as well forget that rand() exists
rand() is also quite slow. I was using a xoshiro256++ algorithm, and it was 4(O0) to 10(O3) times faster, while also having full 64bit range and decent uniformity.
3:49 "Do you ever use any other compiler than MSVC, GCC or Clang?" Meanwhile the real chads who use 'zig c++' for compilation.
that's indeed a chad move
zig cc/c++ calls clang uder the hood
So, clang?
I use pcg random - tiny code, high quality, 32-bits per output (not 15-bits like rand() ), easy to create multiple instances. No "let's think for a bit" reload cost like Mersenne Twister. It's a winner IMHO
Came to say this, pcg is my go-to. Also, there are different versions with larger states (eg, for simulations, where you might want to walk many billions steps and it's good practice to use only a fraction of the state), and they're still really simple and pretty quick.
I could tell the bad ones and the good ones apart since the bad ones made the pigs go to a specific location/direction.
I think it's also worth mentioning that by limiting the range of numbers using the modulo operator for non-powers of 2, you're biasing the lower end of the range of numbers slightly. You should to a long multiply and shift for unbiased ranges.
eh that's the last of the problems, its like the bias will be after 2^32 numbers lol. The real problem is the fact that the lower bits are way worse than the high bits of the output of rand, (you can try that yourself, if you generate a texture using the lowest bit of rand result the result is bad, but if you use the most significant bit you get a very very good quality noise
@ true, but the math pedant in me wants the most "correct" interpretation of the raw result haha, larger ranges might produce more noticeable bias with MSVC's impl only generating numbers up to 32767 too. But ideally you have some better source of random numbers anyway than an LCG.
About copying random number engines: IIRC you're supposed to initialize it once in your project (or at least as few times as possible) and share it between the functions that need to pull random numbers.
About random_device: On GCC before version 9.2 it was deterministic.
why was the first thing that appeared in my mind was the clash of clans diamond drop pattern
So. What's the best implementation?
Just pick it randomly 😆
good one 😂
I looked up some prng values from wikipedia and made my own "random library" that is shitty but is good enough for most applications and is not repeating.
a good way to have a decent uniform distribution is to do the extra few operations required to normalize the output over the range of numbers:
int random(int out_mul) {return (int)(out_mul * (rand() / (float)RAND_MAX));} // preventing integer overflow due to multiplication
is generally better for creating less artifacts in the rand output.
replace the rand() and RAND_MAX values with the ones from your implementation and you have a decent random function for any number, even if it's a bit more time intensive than a single modulus with its double conversions and a division. the time loss on that shouldn't be that critical for most applications and can have the operation reversed to remove the need for conversions if you can guarantee no overflow happens, just like you could reduce the need for modulus with bitwise operations in cases where those cause actual slowdown of the process(had that exact issue before)
If you're coming from rand() without using a random srand(), you should initialize your mt19937 without a random seed too. Just use the constructor without arguments
Did you know that the C++ standard doesn’t require that std::random_device (the pure random number generator) generates purely random numbers? So instead of just requiring that hardware without pure random byte generation instructions don’t support it random_device (which would be sensible and expected behaviour), it insists that they use a PRNG fallback instead.
IDK if it MinGW GCC still does this, but for a few years it would always generate the same sequence of numbers the first time it was called, making it useless for seeding other pRNGs even if you ignored the fact that its numbers aren’t big enough for a full mt19937 seed.
cpp fail moment. Ok sure hardware that doesn't have pure random numbers should just fall back to somethinf different, but what excuse did mingw have :))) at least use some time or some os api function idk
@@lowlevelgamedev9330 I assume the reason for it is to signal to the user that the implementation is using PRNG instead of true RNG but at the same time I think the standard would be better if they forced random_device to throw an exception or compile error/warning when built for hardware without an appropriate hardware instruction.
At least then you could expect consistent and “portable” (for lack of a better word) behaviour. I don’t think there should really be any situation where a generator that’s explicitly for pure randomness has a hidden, implementation-defined pseudorandom fallback behaviour.
but this depends on the implementation. rand() does not standardize a algorythm so the compiler developer can choose.
LLGD my guy! I‘ve been there from almost day one and I have to say: keep up the good work, I love your videos! Also, you look like a Sigma 🗿
thank you bro 💪💪 I'm on it 🗿
Hey ik your working on this project rn, but do you think you could make a few videos on how to use skript correctly?
I don't know what is skript, you can message me on discord tho to clarify 💪
Obviously the better thing to do would be to use FNV-1A, Murmur3 or MeowHash2
Nooooooo this number not random
Add “i ” at the end it will become good
just write your own hash function
chaddest c++ dev
no, rand() is not evil. the compiler is.
timetravellers took over this video
Are you Latvian by any chance? Sounds familiar to me. Know a few latvian people.
yooo pixel dungeon
yesss best game ever
skill issue
I use srand + rand all the time and I never have had any problems using them. Also, nice shirt bro 👌
Only 32768 discrete values. That's generally enough, but not always. I had to make my own "hack" onto this 🙂
Yooo face reveal
omg it's so annoying when people add captions but only for the first 10 seconds of the video like wtf
A good rant about rand()
e
C++ hasn't been fun to code since C++14 for me, after almost 20 years with C++ I just gave up on it. Horrible new features that over complicate things and bizarre new syntax like initializers instead of assignments, no default networking library. I don't know what's new anymore but when I was using C++, there was no true unicode support (not the garbage semi implementation currently) for the string library.
I used to find myself spending a great deal of time configuring mundane property sheets for visual studio for the different libraries and linker problems, that has nothing to do with programming at all, very boring stuff. And importing and compiling external libraries is a pain in the neck.
C99 is the true language of programming bliss. 😂
@@rnts08 Agree, but I really like the concept of objects and polymorphism. I am not sure about Objective-C (Obj-C) since I never used it (probably because it was owned by Apple), but since that one is defunct, I would prefer a similar one.
agreed, that's why I use cpp like it is c 99% of time and I don't have problems like this
I have a video on it but like just use cpp with the things that you want to use from it. I for example don't ever write destructors but I use pre made classes like vector and others
@@lowlevelgamedev9330 I will check it out, thanks. But still, importing libraries and compiling them is a nightmare, I used to juggle 2 or 3 big libraries like wxWidgets, and SDL and few others at the same time. Thinking about the past gives me shivers 😱 Just glancing at new C++23, they seem to have "import" Modules now, not really sure if it is widely adopted though.
hi
Wooo wooo face reveal
first! :P
Games: always rand()
Cryptography: use a decent rng
You wanna just make an rng for fun: xor shift
skill issue