Re: Writing bugs
Posted: Sun Jan 13, 2019 12:30 am
Code: Select all
// SplitMix64 PRNG, by Sebastiano Vigna: http://xoroshiro.di.unimi.it/splitmix64.c
static uint64_t prng(uint64_t *state)
{
uint64_t s = (*state += 0x9E3779B97F4A7C15ULL);
s = (s ^ (s >> 30)) * 0xBF58476D1CE4E5B9ULL;
s = (s ^ (s >> 27)) * 0x94D049BB133111EBULL;
s ^= s >> 31;
assert(s); // We cannot have a zero key for zobrist hashing. If it happens, change the seed.
return s;
}
Code: Select all
rg=random_generator(seed)
r=rg.rand()
There's no variation whatsoever, the modulo simply reduces the output to 15 bits (not useful, wasteful in fact).
you do realise that rg.rand() is C++ syntactic sugar for C's rand(&rg) ?Michel wrote: ↑Sun Jan 13, 2019 9:57 am State is fine but it should be encapsulated in an object. Like so:
The state maintained by the rg object could be much more complicated than a single number (this would likely be the case for a cryptographically secure random generator). The rg object completely hides this state from the user.Code: Select all
rg=random_generator(seed) r=rg.rand()
POSIX-2001 has rand_r for this, but it was declared as obsolete in POSIX-2008 - any idea why?
I meant in actual usage. When you want a small variation, say +/- 50 centipawns, then the usual idiom is to mod the rand() result down like in
Code: Select all
noise = rand()%101 - 50;
The mod down inside rand is useful in fact, and the C ISO standard suggests this for good reason. It would be nonsense to hand out the LCG 32 bit value where the LSB is regularly alternating. Also, RAND_MAX is only specified as at least 32767 anyway in the C standard because an int is only guaranteed to be at least 16 bits.(not useful, wasteful in fact).
Because the notion that "it's bad" is just nonsense. It's unsuited for certain applications, and the one here just is not one of them.I still don't understand why you defend LCG so vehemently. It's bad whether you like it or not.
Ok, not to mention that getting a random in interval by using modulo is not a good idea, you don't get uniform distribution this way unless the value you modulate with is a power of two. It gets worse the smaller the output range is, especially bad if RAND_MAX is only 32k.Ras wrote: ↑Sun Jan 13, 2019 3:28 pm I meant in actual usage. When you want a small variation, say +/- 50 centipawns, then the usual idiom is to mod the rand() result down like in
Code: Select all
noise = rand()%101 - 50;
Yes, legacy limits.The mod down inside rand is useful in fact, and the C ISO standard suggests this for good reason. It would be nonsense to hand out the LCG 32 bit value where the LSB is regularly alternating. Also, RAND_MAX is only specified as at least 32767 anyway in the C standard because an int is only guaranteed to be at least 16 bits.
How many times do I have to show you that LCG is bad You claim it's nonsense, that's your strongest argument I suppose.Because the notion that "it's bad" is just nonsense. It's unsuited for certain applications, and the one here just is not one of them.
Besides, the moiré image issue with MS' rand() isn't even the LGC, it's that they didn't just copy the suggestion from the ISO standard and used 214013 instead of 1103515245 as multiplier, which is too small. No surprise that MS invents something of its own and botches it up, they do that all the time. Use the one from the ISO standard, and you don't get a moiré image, see attachment.
https://en.cppreference.com/w/cpp/numeric/randomMichel wrote: ↑Sun Jan 13, 2019 9:57 am State is fine but it should be encapsulated in an object. Like so:
The state maintained by the rg object could be much more complicated than a single number (this would likely be the case for a cryptographically secure random generator). The rg object completely hides this state from the user.Code: Select all
rg=random_generator(seed) r=rg.rand()