Is it possible to seed the random number generator (Math.random
) in JavaScript?

- 20,365
- 9
- 72
- 105

- 6,181
- 4
- 20
- 10
-
3it is not clear whether you want to seed it so that you get the same results repeatedly for different test runs or whether you want to seed it with 'something unique' per user for better randomness between usage. – simbo1905 May 16 '14 at 05:45
-
5No, unfortunately it is not possible. [jsrand](https://github.com/DomenicoDeFelice/jsrand) is a little library I wrote when I needed a seedable PRNG. There are also other more complex libraries that you can find googling for it. – Domenico De Felice Jan 02 '15 at 18:01
-
12Adding to the question: how is it possibly a good idea to offer a PRNG without a means to seed it?? Is there any good reason for this? – Alan Jul 18 '18 at 17:58
-
1See also https://stackoverflow.com/questions/424292 – Palimondo Mar 26 '20 at 15:28
-
2Here's a visualization of some of the generators on this page https://observablehq.com/@tidwall/hello-randomness – tidwall Sep 15 '20 at 18:39
-
7@Alan I think maybe there's no seed because the underlying algorithm is up to the browser - if Math.random() did have a seed, the seeds would not be guaranteed to give the same results in different browsers. https://hackernoon.com/how-does-javascripts-math-random-generate-random-numbers-ef0de6a20131 – codeulike Jun 02 '21 at 08:44
21 Answers
No, it is not possible to seed Math.random()
. The ECMAScript specification is intentionally vague on the subject, providing no means for seeding nor require that browsers even use the same algorithm. So such a function must be externally provided, which thankfully isn't too difficult.
I've implemented a number of good, short and fast Pseudorandom number generator (PRNG) functions in plain JavaScript. All of them can be seeded and provide high quality numbers. These are not intended for security purposes--if you need a seedable CSPRNG, look into ISAAC.
First of all, take care to initialize your PRNGs properly. To keep things simple, the generators below have no built-in seed generating procedure, but accept one or more 32-bit numbers as the initial seed state of the PRNG. Similar or sparse seeds (e.g. a simple seed of 1 and 2) have low entropy, and can cause correlations or other randomness quality issues, sometimes resulting in the output having similar properties (such as randomly generated levels being similar). To avoid this, it is best practice to initialize PRNGs with a well-distributed, high entropy seed and/or advancing past the first 15 or so numbers.
There are many ways to do this, but here are two methods. Firstly, hash functions are very good at generating seeds from short strings. A good hash function will generate very different results even when two strings are similar, so you don't have to put much thought into the string. Here's an example hash function:
function cyrb128(str) {
let h1 = 1779033703, h2 = 3144134277,
h3 = 1013904242, h4 = 2773480762;
for (let i = 0, k; i < str.length; i++) {
k = str.charCodeAt(i);
h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
}
h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
h1 ^= (h2 ^ h3 ^ h4), h2 ^= h1, h3 ^= h1, h4 ^= h1;
return [h1>>>0, h2>>>0, h3>>>0, h4>>>0];
}
Calling cyrb128
will produce a 128-bit hash value from a string which can be used to seed a PRNG. Here's how you might use it:
// Create cyrb128 state:
var seed = cyrb128("apples");
// Four 32-bit component hashes provide the seed for sfc32.
var rand = sfc32(seed[0], seed[1], seed[2], seed[3]);
// Only one 32-bit component hash is needed for mulberry32.
var rand = mulberry32(seed[0]);
// Obtain sequential random numbers like so:
rand();
rand();
Note: If you want a slightly more robust 128-bit hash, consider MurmurHash3_x86_128, it's more thorough, but intended for use with large arrays.
Alternatively, simply choose some dummy data to pad the seed with, and advance the generator beforehand a few times (12-20 iterations) to mix the initial state thoroughly. This has the benefit of being simpler, and is often used in reference implementations of PRNGs, but it does limit the number of initial states:
var seed = 1337 ^ 0xDEADBEEF; // 32-bit seed with optional XOR value
// Pad seed with Phi, Pi and E.
// https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number
var rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed);
for (var i = 0; i < 15; i++) rand();
Note: the output of these PRNG functions produce a positive 32-bit number (0 to 232-1) which is then converted to a floating-point number between 0-1 (0 inclusive, 1 exclusive) equivalent to Math.random()
, if you want random numbers of a specific range, read this article on MDN. If you only want the raw bits, simply remove the final division operation.
JavaScript numbers can only represent whole integers up to 53-bit resolution. And when using bitwise operations, this is reduced to 32. Modern PRNGs in other languages often use 64-bit operations, which require shims when porting to JS that can drastically reduce performance. The algorithms here only use 32-bit operations, as it is directly compatible with JS.
Now, onward to the the generators. (I maintain the full list with references and license info here)
sfc32 (Simple Fast Counter)
sfc32 is part of the PractRand random number testing suite (which it passes of course). sfc32 has a 128-bit state and is very fast in JS.
function sfc32(a, b, c, d) {
return function() {
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
var t = (a + b) | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = (c << 21 | c >>> 11);
d = d + 1 | 0;
t = t + d | 0;
c = c + t | 0;
return (t >>> 0) / 4294967296;
}
}
You may wonder what the | 0
and >>>= 0
are for. These are essentially 32-bit integer casts, used for performance optimizations. Number
in JS are basically floats, but during bitwise operations, they switch into a 32-bit integer mode. This mode is processed faster by JS interpreters, but any multiplication or addition will cause it to switch back to a float, resulting in a performance hit.
Mulberry32
Mulberry32 is a simple generator with a 32-bit state, but is extremely fast and has good quality randomness (author states it passes all tests of gjrand testing suite and has a full 232 period, but I haven't verified).
function mulberry32(a) {
return function() {
var t = a += 0x6D2B79F5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
}
I would recommend this if you just need a simple but decent PRNG and don't need billions of random numbers (see Birthday problem).
xoshiro128**
As of May 2018, xoshiro128** is the new member of the Xorshift family, by Vigna & Blackman (professor Vigna was also responsible for the Xorshift128+ algorithm powering most Math.random
implementations under the hood). It is the fastest generator that offers a 128-bit state.
function xoshiro128ss(a, b, c, d) {
return function() {
var t = b << 9, r = b * 5; r = (r << 7 | r >>> 25) * 9;
c ^= a; d ^= b;
b ^= c; a ^= d; c ^= t;
d = d << 11 | d >>> 21;
return (r >>> 0) / 4294967296;
}
}
The authors claim it passes randomness tests well (albeit with caveats). Other researchers have pointed out that it fails some tests in TestU01 (particularly LinearComp and BinaryRank). In practice, it should not cause issues when floats are used (such as in these implementations), but may cause issues if relying on the raw lowest order bit.
JSF (Jenkins' Small Fast)
This is JSF or 'smallprng' by Bob Jenkins (2007), who also made ISAAC and SpookyHash. It passes PractRand tests and should be quite fast, although not as fast as sfc32.
function jsf32(a, b, c, d) {
return function() {
a |= 0; b |= 0; c |= 0; d |= 0;
var t = a - (b << 27 | b >>> 5) | 0;
a = b ^ (c << 17 | c >>> 15);
b = c + d | 0;
c = d + t | 0;
d = a + t | 0;
return (d >>> 0) / 4294967296;
}
}

- 12,710
- 6
- 41
- 61
-
-
1I believe the values you quoted from "Tables of Linear Congruential Generators..." by Pierre L’ecuyer could exceed the maximum integer size in Javascript. The max seed of (2^32-1) * 741103597 ≈ 3e18, which is greater than JavaScript's max int size of ≈ 9e15. I think the following values from Pierre's book have the largest period within native limits: `seed = (seed * 185852 + 1) % 34359738337`. – Lachmanski Jun 11 '19 at 03:07
-
2@Lachmanski true, but those are bound by 32-bits (and the Park-Miller 31-bits). Using `Math.imul` allows it to overflow as it would when using multiplication in C on 32-bit integers. What you're suggesting is an LCG utilizing the full range of JS's integer space, which is definitely an interesting area to explore as well. :) – bryc Jun 11 '19 at 12:00
-
2
-
4
-
1Would be nice to have these examples on a page that can be cited without SO in the url (for attribution) – Dec 04 '19 at 09:13
-
5@blobber2 not sure what you mean, but the original code is from here (with others): https://github.com/bryc/code/blob/master/jshash/PRNGs.md. more or less a gist inside a repository :-) – bryc Dec 04 '19 at 20:14
-
thanks for the very useful post! are the a >>>= 0 and a |= 0 some fast ways of casting to 32 bit int? – DrLightman Apr 28 '20 at 09:59
-
1@DrLightman correct - forcing it early, or keeping it always in 32-bit, appears to speed things up. Although now I forget how exactly I measured them. But it could easily be obsolete in the future as JS engines might get smarter. But even now, this example shows that fnv1a hash is 70% slower without `| 0`, in firefox: https://jsbench.me/afk9jv36oz/1. – bryc Apr 28 '20 at 12:13
-
Thanks for the research that went into this, bryc! It still took me a bit to figure out which to use and how to generate an integer 0-n (first used Math.round, tested it, didn't give good results, then used Math.floor, that worked). Maybe add to the "apples" example: `n = Math.floor(rand() * X); // generate random integer below X`? For choosing an algorithm, e.g. JSF says it performs "well" (others perform "without issue", is that better?) and "should" be fast. I see in git you have the numbers, it might help to be more concrete here. Either way, your answer helped me, thanks for the work! – Luc May 01 '20 at 18:00
-
@Luc Thanks, glad it was a help! Some valid criticisms here - I'll add link to MDN for doing ranged numbers. JSF and SFC both pass PractRand, but JSF is a bit slower - I just wrote general observations. I don't want the answer to be TOO long. But I will see if I can make it less confusing. :) – bryc May 01 '20 at 20:45
-
@bryc I see you did quite some work on the post! The MDN reference is a good idea, I didn't know of that page (would have saved me the trial-and-error :) ). One question: "*these are all 32-bit generators*" and a bit later "*sfc32 has a 128-bit state*". Isn't that a contradiction (probably leftover from the previous revision)? – Luc May 01 '20 at 22:17
-
@Luc No, that's correct. These algorithms are ported from 32-bit C code, intended for older 32-bit CPUs. "128-bit state" is just the internal memory size, and implies a collection of four 32-bit words acting as one unit. In JS, bitwise operations are bound by 32-bit words, which is why 32-bit C code can be ported to JS efficiently. Hope that explains it – bryc May 02 '20 at 00:26
-
@bryc So if I understand it correctly, the period will be 2^128 and the "they're all 32-bit" is meant to convey that the algorithms can efficiently be ported from their original C to JavaScript? Because what I guess people care about is the period, not so much how hard the porting work was. Thanks again, by the way :) – Luc May 02 '20 at 11:00
-
1@Luc The state size doesn't define the period, only theoretical max. A minimum period of 2^32 is sufficient for non-cryptographic use. JSF and SFC have an avg period of 2^127 (according to PractRand) which is quite good. And I mention "32-bit" because it is important to understand. Something like [PCG](https://github.com/thomcc/pcg-random/blob/master/pcg-random.js) by its very nature, is inefficient/slow in JS (my goal here is efficiency/speed). It takes more code to reimplement 64-bit multiplication than _any_ of the above PRNGs, and end up running exponentially slower. – bryc May 02 '20 at 19:01
-
Thanks for this code. I do question the use of xmur3 to initialize sfc32. You're initializing 128 bits of seed with only 32 bits of entropy. I think it's better to use a hash that produces a larger result. – Vroo Sep 18 '20 at 02:30
-
@Vroo I'm not that concerned, _PRNG quality > seed quality_, and it is somewhat unavoidable. Due to JS bitwise limitations, 32-bit results must be mixed together. Have a look at [MurmurHash3_x86_128](https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp#L150) - four uncorrelated 32-bit hashes sufficiently mixed produce valid 128-bit hashes. If improved mixing of component hashes does not increase entropy, as used in MurmurHash3_x86_128, then nothing can be done about it~ – bryc Sep 18 '20 at 14:46
-
My point @bryc was that you're not using "four uncorrelated 32-bit hashes," you're using four correlated hashes since xmur3 only has 32 bits of internal state. I'm using your port of sfc32 (thanks!) and am initializing it with a 128 bit hash instead. – Vroo Oct 06 '20 at 05:10
-
@Vroo `xmur3` is indeed correlated, there's no denying that - I was referring to the linked 128-bit hash implementation which was uncorrelated. Unfortunately fixing xmur3 would require quadrupling the code size. Which 128-bit hash are you using? I have not seen much of those in JS. – bryc Oct 14 '20 at 10:56
-
In xmur3, maybe put the first two lines of the for loop in braces for clarity? (I misread the comma for a semicolon and was confused, but maybe it's only me) – Searle Dec 20 '21 at 20:27
-
-
1@Ted No, these are not secure PRNGs. Use the built-in `Crypto.getRandomValues()` for secure random values, but note it cannot be seeded (AFAIK). If you absolutely must have repeatable results for some reason, try [ISAAC](https://github.com/rubycon/isaac.js/blob/master/isaac.js), but it wont be as fast and take up more code. – bryc May 24 '22 at 11:49
-
1@Vroo 2 years later, I've now replaced `xmur3` with an intermixed 128-bit hash. Hopefully its not much worse than `MurmurHash3_x86_128`. Sorry I didn't quite grasp your entropy concern before, I now realize it was misleading to suggest it for initializing a 128-bit state. – bryc May 24 '22 at 19:24
-
-
1@jdbertron It's a hash function I made, similar to [cyrb53](https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript/47593316#47593316) but outputs 128 bits instead of 53. – bryc Jun 15 '22 at 21:03
-
Looks useful. Could you cite sources so we can verify that your implementation matches the design? – Jason S Jan 23 '23 at 05:33
-
Hmm. Actually, your jsf does NOT match the design of https://burtleburtle.net/bob/rand/smallprng.html in three ways: (1) it converts to a floating-point value, (2) it does not take a 32-bit seed used for b,c,d with `a=0xf1ea5eed`, and (3) it does not perform the initial 20 loops to "mix" the random state. – Jason S Jan 23 '23 at 06:06
-
@JasonS (1) Returning float is just to match Math.random output; easily removed if needed. (2,3) Goal is not to provide ready-made libs, but to teach/explain the craft and only provide base generators, while explaining seeding separately. I _do_ provide the original seed procedures (and references) in the [long-form article](https://github.com/bryc/code/blob/master/jshash/PRNGs.md#jsf--smallprng). But it is optional, and using a custom seed generator still retains the quality of the generator, and is sometimes better (larger seed space, etc). – bryc Jan 23 '23 at 20:17
-
Yes but you state "This is JSF or 'smallprng' by Bob Jenkins (2007)." Could you please state that you have a RNG that is based on JSF/smallprng? There is a difference. – Jason S Jan 24 '23 at 04:27
-
it's worth nothing that the xoshiro128** implementation in this answer is based on the 1.0 reference code which [mistakenly used s\[0\] instead of s\[1\] as state word passed to the scrambler](https://prng.di.unimi.it/xoshiro128starstar.c) – relative May 29 '23 at 15:15
-
-
@Boddle I updated `cyrb128` to fix the issue you found. Indeed, what I had was satisfying this equation `(A ^ B ^ C ^ D) === ((A^B) ^ (A^C) ^ (A^D))`, which I guess it shouldn't have. The new solution is similar to what `MurmurHash3_x86_128` does. Also, you should have just commented instead of posting it as an answer. :-) – bryc Jul 27 '23 at 00:33
No, it is not possible to seed Math.random()
, but it's fairly easy to write your own generator, or better yet, use an existing one.
Check out: this related question.
Also, see David Bau's blog for more information on seeding.

- 20,365
- 9
- 72
- 105

- 10,319
- 3
- 37
- 44
NOTE: Despite (or rather, because of) succinctness and apparent elegance, this algorithm is by no means a high-quality one in terms of randomness. Look for e.g. those listed in this answer for better results.
(Originally adapted from a clever idea presented in a comment to another answer.)
var seed = 1;
function random() {
var x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
You can set seed
to be any number, just avoid zero (or any multiple of Math.PI).
The elegance of this solution, in my opinion, comes from the lack of any "magic" numbers (besides 10000, which represents about the minimum amount of digits you must throw away to avoid odd patterns - see results with values 10, 100, 1000). Brevity is also nice.
It's a bit slower than Math.random() (by a factor of 2 or 3), but I believe it's about as fast as any other solution written in JavaScript.

- 18,944
- 13
- 54
- 47
-
25Is there a way to prove this RNG generate numbers that are uniformly distributed? Experimentally it seems to: http://jsfiddle.net/bhrLT/ – Nathan Breit Oct 12 '13 at 14:04
-
11[6,000,000 ops/second](http://jsperf.com/math-random-vs-seeded-rand) is pretty fast, I don't plan on generating more than ~3,000,000 per click. Kidding, this is brilliant. – A.M.K May 02 '14 at 00:11
-
Actually, the smaller the number is, the faster it runs. A Math.random decimal gets ~20,000,000 ops/second. I just updated the jsperf. Either way, this probably won't be a bottleneck in your application. – A.M.K May 02 '14 at 00:20
-
71-1, This isn't a uniform sampler at all - it is quite biased towards 0 and 1 (see http://jsfiddle.net/bhrLT/17/, which may take a while to compute). Consecutive values are correlated - every 355 values, and even more so every 710, are related. Please use something more carefully thought-out! – spencer nelson May 22 '14 at 04:43
-
1
-
1@JasonGoemaat, that's just taking a few extra decimals from the sin function - it's not resolving the core problem, which is that the decimals of sin aren't uniformly distributed. It looks better, but thats just because you need more datapoints to see the nonuniformity. – spencer nelson May 30 '14 at 21:24
-
58The question's not about creating a cryptographically secure random number generator, but something that works in javascript, useful for quick demos, etc. I'll take something quick and simple that gives a good looking distribution over a million random numbers for that purpose. – Jason Goemaat May 31 '14 at 00:08
-
2Looking at the histogram spencer nelson posted, it looks like the uniformity could easily be improved by discarding results outside the range, say [0.1,0.9], and normalising the remaining results from that range to [0,1]. – realh Jun 23 '15 at 17:40
-
2Jason Goemaat : Actualy any mod operation can fit the answer in that case, and for that matter only using sin(x) or mod(x,...) is the same. That's not random number, you can also use permutation to even go faster. The question is then misleading if tricks like this are accepted. I am downvoting it. A random generator should show any correlation, nor frequency pattern, it's stupid. – danbo Sep 01 '15 at 09:12
-
24Be careful. Math.sin() can give different results on client and server. I use Meteor (uses javascript on client & server). – Obiwahn Oct 27 '15 at 16:29
-
1@realh Exactly! http://jsfiddle.net/Llorx/bhrLT/93/ Still not 100% secure for crypto, but the result is more normalized. – Jorge Fuentes González Jan 17 '17 at 12:36
-
2This does create different results on different browsers... chrome, safari firefox all have different results. so if the purpose is to use the seed for consistency, this won't work. – Ray Foss Aug 16 '17 at 20:19
-
2
-
1It’s far from uniform and far from independent. Mathematically speaking, it is ergodic but not even mixing. It will fail the most basic tests involving LLN and CLT. – user334639 Aug 09 '19 at 18:24
-
1There's more correlation to 355 then 710 because it a continued fraction of pi: https://en.wikipedia.org/wiki/Continued_fraction#Continued_fraction_expansions_of_%CF%80 @spencernelson – karpada Apr 26 '20 at 10:52
-
Wouldn't you get a (slightly) better distribution going for Math.tan() instead of Math.sin()? http://jsfiddle.net/g7f9jqr4/2/ – Francois Connetable Mar 16 '23 at 11:10
No, but here's a simple pseudorandom generator, an implementation of Multiply-with-carry I adapted from Wikipedia (has been removed since):
var m_w = 123456789;
var m_z = 987654321;
var mask = 0xffffffff;
// Takes any integer
function seed(i) {
m_w = (123456789 + i) & mask;
m_z = (987654321 - i) & mask;
}
// Returns number between 0 (inclusive) and 1.0 (exclusive),
// just like Math.random().
function random()
{
m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}

- 12,186
- 6
- 68
- 106

- 18,944
- 13
- 54
- 47
-
3
-
3This is the [multiply-with-carry (MWC)](http://en.wikipedia.org/wiki/Multiply-with-carry) random generator with a pretty long period. Adapted from [wikipedia Random Number Generators](http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods) – Michael_Scharf Jul 21 '14 at 15:13
-
When I use it with my random color generator (HSL), it generates only green and cyan colors. The original random generator generates all colors. So, it is not same or it does not work. – Tomas Kubes Dec 07 '14 at 07:13
-
@Michael_Scharf 1) The seed change `m_w`, not `m_z`. 2) Both `m_w` and `m_z` are change BASED on their previous values, so it does modify the result. – ESL Sep 17 '15 at 16:15
-
When I used this code I did not get well-distributed results. Regardless of seed, the output sequence was very similar. This made it not helpful for my game. – Martin Omander Feb 20 '17 at 17:58
-
@Justin this is several years too late, but with several seeds at millions of runs, it's almost perfectly distributed. Variance in distribution was around `3.469446951953614e-18` - i.e. _extremely_ well distributed. [This](https://gist.github.com/Qix-/c01d144472593a27d398619ad6e54c03) is the script I used to test distribution. Just needs an object with a `next()` method. – Qix - MONICA WAS MISTREATED Jun 11 '17 at 23:33
-
Changing the seed does not result in a completely different sequence of random numbers, there is some sort of underlying pattern. This is the [XOR of two bit graphs](https://i.imgur.com/ly3Y1Pk.png) with seed 1 and 55. White pixels are <0.5, black pixels are >0.5. XORing two outputs with different seeds show a bias towards >0.5. – bryc Dec 01 '17 at 12:07
-
I provided an edit to address some serious issues in the code. It was not being properly seeded, and the workaround for negative numbers was causing bias. This is very similar to the MWC1616 algorithm which has a [bad reputation](https://medium.com/@betable/tifu-by-using-math-random-f1c308c4fd9d) as far as quality goes. – bryc Dec 10 '18 at 05:40
-
Antti Sykäri's algorithm is nice and short. I initially made a variation that replaced JavaScript's Math.random
when you call Math.seed(s)
, but then Jason commented that returning the function would be better:
Math.seed = function(s) {
return function() {
s = Math.sin(s) * 10000; return s - Math.floor(s);
};
};
// usage:
var random1 = Math.seed(42);
var random2 = Math.seed(random1());
Math.random = Math.seed(random2());
This gives you another functionality that JavaScript doesn't have: multiple independent random generators. That is especially important if you want to have multiple repeatable simulations running at the same time.

- 44,755
- 7
- 76
- 106
-
4If you return the function instead of setting `Math.random` that would allow you to have multiple independent generators, right? – Jason Goemaat May 29 '14 at 19:38
-
2Be sure to see comments above about distribution of randomness if that matters to you: http://stackoverflow.com/questions/521295/javascript-random-seeds#comment36604417_19303725 – jocull Jun 27 '16 at 14:21
-
How randoms generated by this can be repeated? It keeps giving new numbers every time – SMUsamaShah Dec 25 '16 at 13:11
-
each time you do `Math.seed(42);` it resets the function, so if you do `var random = Math.seed(42); random(); random();` you get `0.70...`, then `0.38...`. If you reset it by calling `var random = Math.seed(42);` again, then the next time you call `random()` you'll get `0.70...` again, and the next time you'll get `0.38...` again. – WOUNDEDStevenJones Dec 07 '17 at 18:53
-
6Please do not use this. Please take the time to instead use a local variable named `random` instead of overwriting a native javascript function. Overwriting `Math.random` may cause the JIST compiler to unoptimize all your code. – Jack G Apr 12 '18 at 22:30
-
Warning not working for s = 0. Should throw error when constructing. – Rok Burgar Mar 07 '19 at 14:41
-
Please see Pierre L'Ecuyer's work going back to the late 1980s and early 1990s. There are others as well. Creating a (pseudo) random number generator on your own, if you are not an expert, is pretty dangerous, because there is a high likelihood of either the results not being statistically random or in having a small period. Pierre (and others) have put together some good (pseudo) random number generators that are easy to implement. I use one of his LFSR generators.
https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf

- 44,755
- 7
- 76
- 106

- 129
- 1
- 2
-
2
-
5The code for implementing Professor L'Ecuyer's work is publicly available for java and readily translatable by most programmers into Javascript. – user2383235 Mar 05 '17 at 23:44
Combining some of the previous answers, this is the seedable random function you are looking for:
Math.seed = function(s) {
var mask = 0xffffffff;
var m_w = (123456789 + s) & mask;
var m_z = (987654321 - s) & mask;
return function() {
m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}
}
var myRandomFunction = Math.seed(1234);
var randomNumber = myRandomFunction();

- 12,710
- 6
- 41
- 61

- 79
- 1
- 2
-
4This produces very similar results at the beginning of the sequence with different seeds. For example, `Math.seed(0)()` returns `0.2322845458984375`, and `Math.seed(1)()` returns `0.23228873685002327`. Changing both `m_w` and `m_z` according to the seed seems to help. `var m_w = 987654321 + s; var m_z = 123456789 - s;` produces a nice distribution of first values with different seeds. – undefined Apr 18 '16 at 20:21
-
2@undefined the issue you described is fixed as of the last edit, it was a bug in the MWC implementation. – bryc Feb 22 '19 at 17:29
-
Working nicely now, as of Jan 2020. Seed with 0, get 0.7322976540308446. Seed with 1, 0.16818441334180534, with 2: 0.6040864314418286, with 3: 0.03998844954185188. Thank you both! – ProfDFrancis Jan 01 '20 at 22:29
-
I'm curious about the `>>> 0` and why it's better than the more straightforward `& mask`. – President James K. Polk Oct 05 '22 at 18:56
It's not possible to seed the builtin Math.random function, but it is possible to implement a high quality RNG in Javascript with very little code.
Javascript numbers are 64-bit floating point precision, which can represent all positive integers less than 2^53. This puts a hard limit to our arithmetic, but within these limits you can still pick parameters for a high quality Lehmer / LCG random number generator.
function RNG(seed) {
var m = 2**35 - 31
var a = 185852
var s = seed % m
return function () {
return (s = s * a % m) / m
}
}
Math.random = RNG(Date.now())
If you want even higher quality random numbers, at the cost of being ~10 times slower, you can use BigInt for the arithmetic and pick parameters where m is just able to fit in a double.
function RNG(seed) {
var m_as_number = 2**53 - 111
var m = 2n**53n - 111n
var a = 5667072534355537n
var s = BigInt(seed) % m
return function () {
return Number(s = s * a % m) / m_as_number
}
}
See this paper by Pierre l'Ecuyer for the parameters used in the above implementations: https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
And whatever you do, avoid all the other answers here that use Math.sin!

- 1,873
- 1
- 13
- 11
To write your own pseudo random generator is quite simple.
The suggestion of Dave Scotese is useful but, as pointed out by others, it is not quite uniformly distributed.
However, it is not because of the integer arguments of sin. It's simply because of the range of sin, which happens to be a one dimensional projection of a circle. If you would take the angle of the circle instead it would be uniform.
So instead of sin(x)
use arg(exp(i * x)) / (2 * PI)
.
If you don't like the linear order, mix it a bit up with xor. The actual factor doesn't matter that much either.
To generate n pseudo random numbers one could use the code:
function psora(k, n) {
var r = Math.PI * (k ^ n)
return r - Math.floor(r)
}
n = 42; for(k = 0; k < n; k++) console.log(psora(k, n))
Please also note that you cannot use pseudo random sequences when real entropy is needed.

- 44,755
- 7
- 76
- 106

- 69
- 1
- 1
-
I'm no expert, but sequential seeds follow a [constant pattern](http://i.imgur.com/LObOzxB.png). Colored pixels are >= 0.5. I am guessing its just iterating over the radius over and over? – bryc Mar 06 '17 at 03:28
-
1"To write your own pseudo random generator is quite simple." -- But to write a correct pseudo random generator is not. – Jason S Jan 23 '23 at 05:26
Math.random
no, but the ran library solves this. It has almost all distributions you can imagine and supports seeded random number generation. Example:
ran.core.seed(0)
myDist = new ran.Dist.Uniform(0, 1)
samples = myDist.sample(1000)

- 7,876
- 4
- 34
- 56
Many people who need a seedable random-number generator in Javascript these days are using David Bau's seedrandom module.

- 3,223
- 28
- 23
Here's the adopted version of Jenkins hash, borrowed from here
export function createDeterministicRandom(): () => number {
let seed = 0x2F6E2B1;
return function() {
// Robert Jenkins’ 32 bit integer hash function
seed = ((seed + 0x7ED55D16) + (seed << 12)) & 0xFFFFFFFF;
seed = ((seed ^ 0xC761C23C) ^ (seed >>> 19)) & 0xFFFFFFFF;
seed = ((seed + 0x165667B1) + (seed << 5)) & 0xFFFFFFFF;
seed = ((seed + 0xD3A2646C) ^ (seed << 9)) & 0xFFFFFFFF;
seed = ((seed + 0xFD7046C5) + (seed << 3)) & 0xFFFFFFFF;
seed = ((seed ^ 0xB55A4F09) ^ (seed >>> 16)) & 0xFFFFFFFF;
return (seed & 0xFFFFFFF) / 0x10000000;
};
}
You can use it like this:
const deterministicRandom = createDeterministicRandom()
deterministicRandom()
// => 0.9872818551957607
deterministicRandom()
// => 0.34880331158638

- 1,535
- 1
- 22
- 23
No, like they said it is not possible to seed Math.random() but you can install external package which make provision for that. i used these package which can be install using these command
npm i random-seed
the example is gotten from the package documentation.
var seed = 'Hello World',
rand1 = require('random-seed').create(seed),
rand2 = require('random-seed').create(seed);
console.log(rand1(100), rand2(100));
follow the link for documentation https://www.npmjs.com/package/random-seed

- 139
- 1
- 5
There are plenty of good answers here but I had a similar issue with the additional requirement that I would like portability between Java's random number generator and whatever I ended up using in JavaScript.
I found the java-random package
These two pieces of code had identical output assuming the seed is the same:
Java:
Random randomGenerator = new Random(seed);
int randomInt;
for (int i=0; i<10; i++) {
randomInt = randomGenerator.nextInt(50);
System.out.println(randomInt);
}
JavaScript:
let Random = require('java-random');
let rng = new Random(seed);
for (let i=0; i<10; i++) {
let val = rng.nextInt(50);
console.log(val);
}

- 621
- 6
- 13
SIN(id + seed) is a very interesting replacement for RANDOM functions that cannot be seeded like SQLite:

- 1,017
- 10
- 11
Most of the answers here produce biased results. So here's a tested function based on seedrandom library from github:
!function(f,a,c){var s,l=256,p="random",d=c.pow(l,6),g=c.pow(2,52),y=2*g,h=l-1;function n(n,t,r){function e(){for(var n=u.g(6),t=d,r=0;n<g;)n=(n+r)*l,t*=l,r=u.g(1);for(;y<=n;)n/=2,t/=2,r>>>=1;return(n+r)/t}var o=[],i=j(function n(t,r){var e,o=[],i=typeof t;if(r&&"object"==i)for(e in t)try{o.push(n(t[e],r-1))}catch(n){}return o.length?o:"string"==i?t:t+"\0"}((t=1==t?{entropy:!0}:t||{}).entropy?[n,S(a)]:null==n?function(){try{var n;return s&&(n=s.randomBytes)?n=n(l):(n=new Uint8Array(l),(f.crypto||f.msCrypto).getRandomValues(n)),S(n)}catch(n){var t=f.navigator,r=t&&t.plugins;return[+new Date,f,r,f.screen,S(a)]}}():n,3),o),u=new m(o);return e.int32=function(){return 0|u.g(4)},e.quick=function(){return u.g(4)/4294967296},e.double=e,j(S(u.S),a),(t.pass||r||function(n,t,r,e){return e&&(e.S&&v(e,u),n.state=function(){return v(u,{})}),r?(c[p]=n,t):n})(e,i,"global"in t?t.global:this==c,t.state)}function m(n){var t,r=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(r||(n=[r++]);e<l;)i[e]=e++;for(e=0;e<l;e++)i[e]=i[o=h&o+n[e%r]+(t=i[e])],i[o]=t;(u.g=function(n){for(var t,r=0,e=u.i,o=u.j,i=u.S;n--;)t=i[e=h&e+1],r=r*l+i[h&(i[e]=i[o=h&o+t])+(i[o]=t)];return u.i=e,u.j=o,r})(l)}function v(n,t){return t.i=n.i,t.j=n.j,t.S=n.S.slice(),t}function j(n,t){for(var r,e=n+"",o=0;o<e.length;)t[h&o]=h&(r^=19*t[h&o])+e.charCodeAt(o++);return S(t)}function S(n){return String.fromCharCode.apply(0,n)}if(j(c.random(),a),"object"==typeof module&&module.exports){module.exports=n;try{s=require("crypto")}catch(n){}}else"function"==typeof define&&define.amd?define(function(){return n}):c["seed"+p]=n}("undefined"!=typeof self?self:this,[],Math);
function randIntWithSeed(seed, max=1) {
/* returns a random number between [0,max] including zero and max
seed can be either string or integer */
return Math.round(new Math.seedrandom('seed' + seed)()) * max
}
test for true randomness of this code: https://es6console.com/kkjkgur2/

- 4,743
- 35
- 37
Do what bryc suggests ... but before you use his cyrb128 hash function to initialise, note that the return statement throws away 32 bits of entropy. Exclusive-or the four values together = 0. You should probably make the first element (h2^h3^h4) >>> 0.

- 13
- 4
-
That's a bug. Fixed. though you should have made a comment instead of a separate answer. ;) – bryc Jul 27 '23 at 00:40
-
Thanks for the acknowledgment, bryc, I agree but not enough reputation to comment – Boddle Jul 28 '23 at 09:06
I have written a function that returns a seeded random number, it uses Math.sin to have a long random number and uses the seed to pick numbers from that.
Use :
seedRandom("k9]:2@", 15)
it will return your seeded number the first parameter is any string value ; your seed. the second parameter is how many digits will return.
function seedRandom(inputSeed, lengthOfNumber){
var output = "";
var seed = inputSeed.toString();
var newSeed = 0;
var characterArray = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','y','x','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','U','R','S','T','U','V','W','X','Y','Z','!','@','#','$','%','^','&','*','(',')',' ','[','{',']','}','|',';',':',"'",',','<','.','>','/','?','`','~','-','_','=','+'];
var longNum = "";
var counter = 0;
var accumulator = 0;
for(var i = 0; i < seed.length; i++){
var a = seed.length - (i+1);
for(var x = 0; x < characterArray.length; x++){
var tempX = x.toString();
var lastDigit = tempX.charAt(tempX.length-1);
var xOutput = parseInt(lastDigit);
addToSeed(characterArray[x], xOutput, a, i);
}
}
function addToSeed(character, value, a, i){
if(seed.charAt(i) === character){newSeed = newSeed + value * Math.pow(10, a)}
}
newSeed = newSeed.toString();
var copy = newSeed;
for(var i=0; i<lengthOfNumber*9; i++){
newSeed = newSeed + copy;
var x = Math.sin(20982+(i)) * 10000;
var y = Math.floor((x - Math.floor(x))*10);
longNum = longNum + y.toString()
}
for(var i=0; i<lengthOfNumber; i++){
output = output + longNum.charAt(accumulator);
counter++;
accumulator = accumulator + parseInt(newSeed.charAt(counter));
}
return(output)
}

- 4,854
- 9
- 34
- 62

- 30
- 9
-
1The sequences of numbers produced by this don't really approximate the properties of sequences of random numbers. Generate 15 numbers with it and the resulting string almost always begins with a 7 for nearly any key, for example. – Gabriel Jun 25 '18 at 18:44
A simple approach for a fixed seed:
function fixedrandom(p){
const seed = 43758.5453123;
return (Math.abs(Math.sin(p)) * seed)%1;
}

- 846
- 10
- 23
In PHP, there is function srand(seed)
which generate fixed random value for particular seed.
But, in JS, there is no such inbuilt function.
However, we can write simple and short function.
Step 1: Choose some Seed (Fix Number).
var seed = 100;
Number should be Positive Integer and greater than 1, further explanation in Step 2.
Step 2: Perform Math.sin() function on Seed, it will give sin value of that number. Store this value in variable x.
var x;
x = Math.sin(seed); // Will Return Fractional Value between -1 & 1 (ex. 0.4059..)
sin() method returns a Fractional value between -1 and 1.
And we don't need Negative value, therefore, in first step choose number greater than 1.
Step 3: Returned Value is a Fractional value between -1 and 1.
So mulitply this value with 10 for making it more than 1.
x = x * 10; // 10 for Single Digit Number
Step 4: Multiply the value with 10 for additional digits
x = x * 10; // Will Give value between 10 and 99 OR
x = x * 100; // Will Give value between 100 and 999
Multiply as per requirement of digits.
The result will be in decimal.
Step 5: Remove value after Decimal Point by Math's Round (Math.round()) Method.
x = Math.round(x); // This will give Integer Value.
Step 6: Turn Negative Values into Positive (if any) by Math.abs method
x = Math.abs(x); // Convert Negative Values into Positive(if any)
Explanation End.
Final Code
var seed = 111; // Any Number greater than 1
var digit = 10 // 1 => single digit, 10 => 2 Digits, 100 => 3 Digits and so. (Multiple of 10)
var x; // Initialize the Value to store the result
x = Math.sin(seed); // Perform Mathematical Sin Method on Seed.
x = x * 10; // Convert that number into integer
x = x * digit; // Number of Digits to be included
x = Math.round(x); // Remove Decimals
x = Math.abs(x); // Convert Negative Number into Positive
Clean and Optimized Functional Code
function random_seed(seed, digit = 1) {
var x = Math.abs(Math.round(Math.sin(seed++) * 10 * digit));
return x;
}
Then Call this function using
random_seed(any_number, number_of_digits)
any_number is must and should be greater than 1.
number_of_digits is optional parameter and if nothing passed, 1 Digit will return.
random_seed(555); // 1 Digit
random_seed(234, 1); // 1 Digit
random_seed(7895656, 1000); // 4 Digit

- 85
- 1
- 4
-
2This function is biased as abs(Math.sin(random_number)) is itself a function biased around the point where slope of sin function is zero. Here's the code that can be run in js console for experiment: (https://pastebin.com/kJyHaQYY) – penduDev Jan 30 '21 at 09:35
For a number between 0 and 100.
Number.parseInt(Math.floor(Math.random() * 100))

- 1
- 1
-
5The question is about seeding `Math.random` such that whenever `Math.random` is seeded with the same seed, it will produce the same successive series of random numbers. This question is not, per say, about the actual usage/demonstration of `Math.random`. – Jack G Apr 12 '18 at 22:38