Last active
March 30, 2025 04:16
-
Star
(118)
You must be signed in to star a gist -
Fork
(8)
You must be signed in to fork a gist
-
-
Save blixt/f17b47c62508be59987b to your computer and use it in GitHub Desktop.
A very simple, seedable JavaScript PRNG. NOTE: Please read comments on why this is not a good choice.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOTICE 2020-04-18 | |
// Please see the comments below about why this is not a great PRNG. | |
// Read summary by @bryc here: | |
// https://github.com/bryc/code/blob/master/jshash/PRNGs.md | |
// Have a look at js-arbit which uses Alea: | |
// https://github.com/blixt/js-arbit | |
/** | |
* Creates a pseudo-random value generator. The seed must be an integer. | |
* | |
* Uses an optimized version of the Park-Miller PRNG. | |
* http://www.firstpr.com.au/dsp/rand31/ | |
*/ | |
function Random(seed) { | |
this._seed = seed % 2147483647; | |
if (this._seed <= 0) this._seed += 2147483646; | |
} | |
/** | |
* Returns a pseudo-random value between 1 and 2^32 - 2. | |
*/ | |
Random.prototype.next = function () { | |
return this._seed = this._seed * 16807 % 2147483647; | |
}; | |
/** | |
* Returns a pseudo-random floating point number in range [0, 1). | |
*/ | |
Random.prototype.nextFloat = function (opt_minOrMax, opt_max) { | |
// We know that result of next() will be 1 to 2147483646 (inclusive). | |
return (this.next() - 1) / 2147483646; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@bryc Sorry, I didn't mean to use the
Math.imul
version of the code in my "correct" example, that was an error on my part.The main point I was trying to make is, using 2^31-1 (= 2147483647) as a modulus is clever because 2147483647 is prime, and in particular, you will not have problems with there being a pattern to the low bits. When you switch to using & or Math.imul, it's not the same algorithm, and it's known to have way worse properties because the modulus is a power of two. There is at least one place above in this thread where the switch is quietly made from a prime modulus to a power-of-two modulus, keeping the numbers 16807 and 2^31-1 in there, and it's hard to spot, because there's a comment stating it's the same algorithm.
Anyway, for my purposes (generating some predictable randomness simply and efficiently for randomized unit tests), I actually like the original LCG.