1

The following snippet of code is taken from a Pseudo-random number generator (written in ActionScript 3):

public function random():Number {
    _currentSeed = (_currentSeed * 16807) % 2147483647);
    return (_currentSeed/0x7FFFFFFF) + 0.000000000233;
}

The first line of the code is easy to understand, it's a standard linear congruential generator, with the multiplier being 16807. The first part of the second line converts the resulting integer to a float roughly between 0 and 1.

However, what is the purpose of that last part of the second line, + 0.000000000233? Is it necessary in such an RNG, or does it serve a different purpose?

Makoto
  • 104,088
  • 27
  • 192
  • 230
IQAndreas
  • 8,060
  • 8
  • 39
  • 74

3 Answers3

3

If you look at the rest of the formula, you'll see that a _currentSeed value of 0 will always result in the same value of 0. Adding (0.5/0x7fffffff), prevents it from ever getting stuck on 0, but is small enough to also prevent it from returning a value >= 1.

To be fair, I wrote that code more than 6 years ago, so I might be remembering wrong, but I'm fairly certain that's the reasoning.

IQAndreas
  • 8,060
  • 8
  • 39
  • 74
gskinner
  • 2,478
  • 11
  • 12
  • Well, that would theoretically make sense, however, the value `0.000000000233` is never actually added to the value of `_currentSeed`, it is only added to the float returned by the function. In fact, if `_currentSeed` is ever set to `0`, it will still continue to return `0` all the time anyway, even with your "safeguard" in place. – IQAndreas May 05 '14 at 02:14
1

The bulk of the algorithm is a well-known prime modulus multiplicative linear congruential generator. All those prefix adjectives mean that it achieves maximum cycle length without the additive term that generalized LCGs have, so PMMLCGs were popular dating back to the 1950's because you did one less operation per invocation. You should never initialize _currentSeed to zero, and the algorithm is designed to never yield a zero or negative number if properly implemented and seeded because it's based on integer arithmetic, which is precise. (Proper implementation means insuring the results aren't affected by integer overflow. A portable algorithm to do this was written in FORTRAN by Linus Schrage back in 1959, along with a simple test consisting of what the seed value ought to be after 1000 iterations.)

The magic number is slightly bigger than (1/2) / 0x7fffffff, so it shouldn't push the return value up over 1. Since it's not being added to _currentSeed, it plays no role in avoiding the fixed-point behavior that would happen if _currentSeed was ever set to zero. Honestly, I can't see that it is accomplishing much of anything.

pjs
  • 18,696
  • 4
  • 27
  • 56
-1

I think, for some reason, _currentSeed could be a negative value because _currentSeed is a signed integer. Adding 0.000000000233 (0.5/0x7fffffff) to the value could avoid this situation.

IQAndreas
  • 8,060
  • 8
  • 39
  • 74
Xing Fei
  • 287
  • 1
  • 6
  • Well, actually, looking at the rest of the code that I linked to, `_currentSeed` is an **unsigned** integer. Even if it was signed, and was ever negative, adding such a tiny value would never be enough of a push to make it positive. – IQAndreas May 05 '14 at 02:18