Generate random numbers based off of a seed value - javascript

Someone brought up the idea of generating random numbers in the exact same order based off of a seed value, and I started thinking extremely hard on how to do this. We challenged eachother to create an application that does the following:
Generate a set of five random numbers ranging from 1 to 100 every ten seconds based on a seed value. The numbers generated (while using the same seed value) should be exactly the same and generated in exactly the same order, therefor if the application is ran for 20 seconds and the numbers [1, 17, 2, 58, 27, 83, 32, 56, 27, 4] are generated, if the application is restarted these exact same numbers should be generated after 20 seconds, if the same seed was provided.
This will allow for multiple clients to generate the same exact information based off of a single numeric seed value.
Unfortunately after a few days we've both ended up falling short and we're completely clueless as to how to do this. We don't even really know what the proper term for this type of behavior is, however I've called it "Deterministic number generation"
I've tagged both languages that we tried using for this expirement, hoping someone can help us out. This would be a very interesting block of code to experiment with, and we've even thought of ways to improve some of our mobile games by using this strategy, if we can find a way to do it.
Any help would be graciously appreciated.

At risk of stating the obvious, but in C# this would be -
int seed = 12;
Random r = new Random(seed);
for (int n = 0; n < 20; n++)
{
Console.WriteLine("{0}", r.Next(1, 100));
}
Where as long as you both use the same seed number you should get the same list ...
Unless I a missing something in your question here ...

Related

Is there any way to generate a random permutation of integers without storing an array?

For context, I am trying to create a feed of random users for an app I'm making, and I would like this to be a non-repeating feed (until of course you visit every user's profile). Suppose I have some users, indexed from 0 to X (so X+1 users, we disregard the user logged in). One way of going about this is creating an array and then applying the Fisher-Yates shuffle to obtain a random permutation, and then sticking with that permutation.
However, my requirements are a little different. I'd like to generate a seed on the client-side and avoid having to generate an array like this, so the only data I send from my client is for pagination: (offset, limit, seed).
It is, at its core, a random bijective mapping between the ranges [0, X] and [0, X]. Fundamentally this is a random permutation, but this comes with the overhead of storing the entire array. If I have 1 million entries it doesn't make sense to have to generate this array just to reach an arbitrary index.
In essence, is there a function which I can feed in an offset (x), limit (y), and seed such that it is able to compute the integer at position x in this random sequence of unique integers (which can be reproduced given the seed) between 0 and DB_SIZE (0 <= x <= DB_SIZE), and then computes the y integers appearing after it? This should be done in O(1) time and space and without having the compute the x-1 integers that come before x in this sequence. (Edit: limit here is the number of elements to retrieve after index x, inclusive. So if I want to grab the next 10 users, I would return, in traditional pagination, items at indices x, x + 1, ... , x + 9. Now these should be mapping to a random sequence of indices, say [29, 57, 61, 1, 5, 30, 11, 70, 94, 7].
Is there any way for me to accomplish this?
Sidenote: Yes, after a user browses through 100 other users it is unlikely that the user would notice a repeat in the first place, so I could theoretically just ensure I have 100 unique users instead and then generate another 100 after this is exhausted (which may contain repeats from the previous 100, or however many before). That is an implementation I might have to fall back on, but I was wondering if this is remotely possible.
As jabaa said in the comments, all you need is a seed. The seed should be a large prime number.
// Potential seeds. These aren't very large, nor are there enough of them.
const seeds = [1299631, 1299637, 1299647, 1299653, 1299673, 1299689];
const seed = seeds[Math.floor(Math.random() * seeds.length)];
function getUserAtN(offset, limit, seed) {
return ((offset + 1) * seed) % limit;
}
function getListOfUsers(numberOfUsers, listLength) {
return Array(listLength).fill(0).map((_, i) => getUserAtN(i, numberOfUsers, seed));
}
console.log("The list is shuffled.", getListOfUsers(10, 20));
console.log("A user can be reliably found.", getUserAtN(3, 10, seed));
You should use format-preserving encryption (fpe). There are implementations in Javascript available.
With fpe you can bijectice relate an integer interval with a given seed.

Identifying a center with squared distance function in plain JavaScript

I can't figure out how to solve the following problem in plain JavaScript.
I have a set of numbers, (e.g. 5, 10, 35, -30, 3), and I am looking for the 'center' of these numbers. My center is supposed to be the point where the sum of the squared distances to all other points is minimal. I think it's the one-dimensional version of the problem of least squares.
Any help would be appreciated. I do not need exact results so a heuristic approach might work as well. It has to work with negative values though.
If you are allowed to pick any real number, then the number you seek is the mean of your numbers.
If you have to pick from a restricted subset (eg integers, or one of the original numbers) then you want the element from that subset that is closest to the mean.
Both of these assertions follow from:
Let Q(y) = Sum{ 1<=i<=N | (X[i]-y)*(X[i]-y}
If m = Sum{ 1<=i<=N | X[i]}/N (ie the mean)
then for any d
Q(m+d) = Q(m) + N*d*d

Purpose of dividing by 1 javascript

I was working on a simple programming exercise my teacher gave us, and I noticed several times that in Javascript, I have to divide a number by 1, otherwise it will return a ridiculous value. Any explanations?
I have a jsfiddle
http://jsfiddle.net/TpNay/1/
var widthrand=Math.floor(Math.random()*widthRange);
width=widthrand + document.getElementById('width').value/1;
If you look at line 22, and take out the divide by 1, and click generate, it will return ridiculous lengths
Thanks
It makes JavaScript type juggle forcing the value of document.getElementById('width').value to become numeric.
A better way to do it would be parseInt(document.getElementById('width').value, 10)

True or better Random numbers with Javascript [duplicate]

This question already has answers here:
Secure random numbers in javascript?
(10 answers)
Closed 12 months ago.
I have all kinds of resources that rely on javascript random numbers. However, I've been seeing a lot of problems where random isn't so random because of the way I'm generating random numbers.
Is there any javascript resource for me to generate true, or just better random numbers?
I know that I can interface with Random.org, but what other options do I have?
I'm using:
function rand( lowest, highest){
var adjustedHigh = (highest - lowest) + 1;
return Math.floor(Math.random()*adjustedHigh) + parseFloat(lowest);
}
Assuming you're not just seeing patterns where there aren't any, try a Mersenee Twister (Wikipedia article here). There are various implementations like this one on github.
Similar SO question:
Seedable JavaScript random number generator
If you want something closer to truly random, then consider using the random.org API to get truly random numbers, although I would suggest only using that to seed, not for every number, as you need to abide by their usage limits.
Tweaking numbers so they "look random"
I agree with Phil H that humans are so good at finding patterns that they often think they see patterns even in "perfectly random" sequences of numbers (clustering illusion, apophenia, gambler's fallacy, etc).
Plots of true random positions generally have lots of clumps and points that "coincidentally" fall very close together, which looks pretty suspicious.
Artists often take completely randomly generated patterns and "nudge" them to make them appear "more random", even though that careful nudging actually makes the pattern less random (a), (b), (c), (d), etc.
Alternatively, a low-discrepancy sequence sometimes "looks better" than a true random sequence and is much faster to generate.
Fast random number generators
There are many "random number generators" across a whole spectrum from "extremely fast" to "relatively slow" and from "easy for even a human to see patterns" to "unlikely that unassisted humans could ever see any patterns" to "cryptographically secure and, after seeded with adequate amounts of entropy, as far as we can tell, indistinguishable from random to any attacker using less than all the energy produced by humanity for a month."
Non-cryptographic-strength random number generators that still give excellent output (unlikely that unassisted humans could ever see any patterns) include the Mersenne twister, multiply-with-carry, Lagged Fibonacci generator, Well equidistributed long-period linear, Xorshift, etc.
Cryptographic random number techniques that work with some browsers
I hear that Cryptocat and other JavaScript applications use the convenient window.crypto.getRandomValues() or window.msCrypto.getRandomValues() or SubtleCrypto.generateKey() functions that are designed to generate cryptographic random numbers. Unfortunately, that function is not available in IE 11 and below.
Since web browsers use random numbers all the time (for every "https://" page they fetch), it's quite likely that these functions (where available) may run faster than most random number generators written in JavaScript -- even non-cryptographic algorithms.
Cryptographic random number techniques compatible with ancient and modern browsers
One way to generate true random numbers in JavaScript is to capture mouse events and add them into a pool of entropy, keeping track of some (hopefully conservative) estimate of the entropy added. Once the pool is "full" (estimates indicate that at least 128 bits of entropy have been added), use some cryptographically secure random number generator to generate random numbers from the pool -- typically by using a one-way hash so that a sequence of a few thousand output numbers are not enough to deduce the state of the entropy pool and hence predict the next output number.
One implementation: http://lightsecond.com/passphrase.html
Further reading
window.crypto
Compatibility of window.crypto.getRandomValues()
Secure random numbers in javascript?
https://security.stackexchange.com/questions/20029/generate-cryptographically-strong-pseudorandom-numbers-in-javascript
Is there any built in browser support for crypto random numbers in IE and Webkit? Firefox has window.crypto
Better random function in JavaScript
While looking for an alternative for Math.random I stumbled on this question.
While those are valid answers, the solution that worked for me was simply using Math.random twice.
And use a modulus on the decimals of the float.
Basically to increase the randomness.
Maybe it might be usefull for some who were guided by google to this question.
Here's a snippet with the function, and one that runs it a million times.
function rand(min, max){
return (Math.floor(Math.pow(10,14)*Math.random()*Math.random())%(max-min+1))+min;
}
// testing rand
function rollRands(min, max, rolls) {
let roll = 0, n = 0;
let counts = {};
for(let i = min; i <= max; i++){
counts[i]=0
}
while (roll < rolls){
roll++;
counts[rand(min,max)]++;
}
return counts;
}
console.log(rollRands(36, 42, 1000000));
Rando.js is cryptographically secure. It's basically window.crypto.getRandomValues() that uses window.msCrypto.getRandomValues() as a failsafe and Math.random() as a last resort failsafe, but it's easier to implement and use. Here's a basic cryptographically secure random [0, 1) number:
console.log(rando());
<script src="https://randojs.com/2.0.0.js"></script>
Nice and easy. If that's all you wanted, you're good to go. If you want it to do more for you, it's also capable of all this:
console.log(rando(5)); //an integer between 0 and 5 (could be 0 or 5));
console.log(rando(5, 10)); //a random integer between 5 and 10 (could be 5 or 10));
console.log(rando(5, "float")); //a floating-point number between 0 and 5 (could be exactly 0, but never exactly 5));
console.log(rando(5, 10, "float")); //a floating-point number between 5 and 10 (could be exactly 5, but never exactly 10));
console.log(rando(true, false)); //either true or false
console.log(rando(["a", "b"])); //{index:..., value:...} object representing a value of the provided array OR false if array is empty
console.log(rando({a: 1, b: 2})); //{key:..., value:...} object representing a property of the provided object OR false if object has no properties
console.log(rando("Gee willikers!")); //a character from the provided string OR false if the string is empty. Reoccurring characters will naturally form a more likely return value
console.log(rando(null)); //ANY invalid arguments return false
//Prevent repetitions by grabbing a sequence and looping through it
console.log(randoSequence(5)); //an array of integers from 0 through 5 in random order
console.log(randoSequence(5, 10)); //an array of integers from 5 through 10 in random order
console.log(randoSequence(["a", "b"])); //an array of {index:..., value:...} objects representing the values of the provided array in random order
console.log(randoSequence({a: 1, b: 2})); //an array of {key:..., value:...} objects representing the properties of the provided object in random order
console.log(randoSequence("Good gravy!")); //an array of the characters of the provided string in random order
console.log(randoSequence(null)); //ANY invalid arguments return false
<script src="https://randojs.com/2.0.0.js"></script>
It supports working with jQuery elements too, but I left that out of this demo so I wouldn't have to source in jQuery. If you need that, just check it out on the GitHub or website.
There seems to be slight confusion here between two things that are very different:
random numbers;
pseudorandom numbers.
Apologies to those who know this already, but the two are worlds apart. Pseudorandom numbers appear random and may even pass sophisticated tests of randomness, but they are deterministic. Because of this, they are useless for cryptography, and may have other flaws where true randomness is required.
True randomness is non-deterministic, and thus unpredictable. A key concept here is one of entropy, or the amount of non-redundant information contained. There is a limited number of ways of obtaining truly random data. 'Good' sources are:
Radioactive decay — often difficult to do;
Background radio noise — contrary to popular believe, this is mostly not related to the background microwave radiation from the big bang, but more parochial;
The noise from electrons moving across a reverse-biased Zener diode: actually quite useful and easy to implement in practice, with simple circuitry.
Other 'sources of randomness' like mouse movements and internal variations in computer disk timing, etc. are often harnessed, but may be less-than-perfect. Generally, I've found that it's easier to access the entropy pool on a Linux system than under Windows, but this may just be personal bias.
If you just want random-appearing numbers, then yes, using the Mersenne twister is a viable option. It jumps around like crazy. If you're generating random numbers to use as e.g. version 4 UUIDs, then you need to be more careful. You can't simply 'add entropy' if it's not there, even by applying deterministic cryptographic functions.
If you intend to use your randomness for cryptography, you should also be intensely aware of the many ways your source of randomness can become compromised. For example, if you're using an Internet-based 'source of randomness', who can tap into this?
Even better, you can use quantum cryptography to generate randomness that is very hard to predict. You can use the ANU Quantum Random Numbers API for some randomness that is coercible into a number similarly output by Math.random.
you can generate a pool of random numbers just by requesting some data asynchronously because performance.now() gives you time precision up to microseconds. Then use the response time as a salt in a randomising algorithm,
var randomNumbers = [];
for(var i = 0; i < 10; i++) {
setTimeout(function () {
var timeStart = performance.now();
xhttp = new XMLHttpRequest();
xhttp.open('GET', 'https://cdn.polyfill.io/v2/polyfill.min.js?rand=' + Math.random(), true);
xhttp.onload = function () {
var timeEnd = performance.now() - timeStart;
var rNumber = parseInt(timeEnd.toString().replace('.', ''));
randomNumbers.push(rNumber)
};
xhttp.send();
}, i * 10);
}
There are many factors that will affect this time:
browser speed
route one way
server response time
route back
It's not good to generate millions of numbers this way but a few. Maybe concatenate a few results to get a good, long random number.

Influence Math.random()

I'm looking for a way to influence Math.random().
I have this function to generate a number from min to max:
var rand = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Is there a way to make it more likely to get a low and high number than a number in the middle?
For example; rand(0, 10) would return more of 0,1,9,10 than the rest.
Is there a way to make it more likely to get a low and high number than a number in the middle?
Yes. You want to change the distribution of the numbers generated.
http://en.wikipedia.org/wiki/Random_number_generation#Generation_from_a_probability_distribution
One simple solution would be to generate an array with say, 100 elements.
In those 100 elements represent the numbers you are interested in more frequently.
As a simple example, say you wanted number 1 and 10 to show up more frequently, you could overrepresent it in the array. ie. have number one in the array 20 times, number 10 in the array 20 times, and the rest of the numbers in there distributed evenly. Then use a random number between 0-100 as the array index. This will increase your probability of getting a 1 or a 10 versus the other numbers.
You need a distribution map. Mapping from random output [0,1] to your desired distribution outcome. like [0,.3] will yield 0, [.3,.5] will yield 1, and so on.
Sure. It's not entirely clear whether you want a smooth rolloff so (for example) 2 and 8 are returned more often than 5 or 6, but the general idea works either way.
The typical way to do this is to generate a larger range of numbers than you'll output. For example, lets start with 5 as the base line occurring with frequency N. Let's assume that you want 4 or 7 to occur at frequency 2N, 3 or 8 at frequency 3N, 2 or 9 and frequency 4N and 0 or 10 at frequency 5N.
Adding those up, we need values from 1 to 29 (or 0 to 28, or whatever) from the generator. Any of the first 5 gives an output of 0. Any of the next 4 gives and output of 1. Any of the next 3 gives an output of 2, and so on.
Of course, this doesn't change the values returned by the original generator -- it just lets us write a generator of our own that produces numbers following the distribution we've chosen.
Not really. There is a sequence of numbers that are generated based off the seed. Your random numbers come from the sequence. When you call random, you are grabbing the next element of the sequence.
Can you influence the output of Math.random in javascript (which runs client side)?
No. At least not in any feasible/practical manner.
But what you could do is to create your own random number generator that produces number in the distribution that you need.
There are probably an infinite number of ways of doing it, and you might want to think about the exact shape/curvature of the probability function.
It can be probably be done in one line, but here is a multi-line approach that uses your existing function definition (named rand, here):
var dd = rand(1,5) + rand(0,5);
var result;
if (dd > 5)
result = dd - 5;
else result = 6 - dd;
One basic result is that if U is a random variable with uniform distribution and F is the cumulative distribution you want to sample from, then Y = G(X) where G is the inverse of F has F as its cumulative distribution. This might not necessarily be the most efficient way of doing and generating random numbers from all sort of distributions is a research subfield in and of itself. But for a simple transformation it might just do the trick. Like in your case, F(x) could be 4*(x-.5)^3+.5, it seems to satisfy all constraints and is easy to invert and use as a transformation of the basic random number generator.

Categories

Resources