I am trying to create a custom linear congruential generator (LCQ) in JavaScript (the one used in glibc).
Its properties as it's stated on Wikipedia are: m=2^31 , a=1103515245 , c=12345.
Now I am getting next seed value with
x = (1103515245 * x + 12345) % 0x80000000 ; // (The same as &0x7fffffff)
Although the generator seems to work, but when the numbers are tested on canvas:
cx = (x & 0x3fffffff) % canvasWidth; // Coordinate x (the same for cy)
They seem to be horribly biased: http://jsfiddle.net/7VmR9/3/show/
Why does this happen? By choosing a different modulo, the result of a visual test looks much better.
The testing JSFiddle is here: http://jsfiddle.net/7VmR9/3/
Update
At last I fixed the transformation to canvas coordinates as in this formula:
var cx = ((x & 0x3fffffff)/0x3fffffff*canvasWidth)|0
Now the pixel coordinates are not so much malformed as when used the modulo operation.
Updated fiddle: http://jsfiddle.net/7VmR9/14/
For the generator the formula is (you forgot a modulus in the first part):
current = (multiplier * current * modul + addend) % modulus) / modulus
I realize that you try to optimize it so I updated the fiddle with this so you can use it as a basis for the optimizations:
http://jsfiddle.net/AbdiasSoftware/7VmR9/12/
Yes, it looks like you solved it. I've done the same thing.
A linear congruential generator is in the form:
seed = (seed * factor + offset) % range;
But, most importantly, when obtaining an actual random number from it, the following does not work:
random = seed % random_maximum;
This won't work because the second modulus seems to counteract the effect of the generator. Instead, you need to use:
random = floor (seed / range * random_maximum);
(This would be a random integer; remove the floor call to obtain a random float.)
Lastly, I will warn you: In JavaScript, when working with numbers that exceed the dword limit, there is a loss of precision. Thus, the random results of your LCG may be random, but they most likely won't match the results of the same LCG implemented in C++ or another low-level language that actually supports dword math.
Also due to imprecision, the cycle of the LCG is highly liable to be greatly reduced. So, for instance, the cycle of the glibc LCG you reference is probably 4 billion (that is, it will generate over 4 billion random numbers before starting over and re-generating the exact same set of numbers). This JavaScript implementation may only get 1 billion, or perhaps far less, due to the fact that when multiplying by the factor, the number surpasses 4 billion, and loses precision in doing so.
Related
Context
I was looking at this video DHE explained
It talks about how two people can exchange a key without eyedroppers to know much.
The implementation according to the video
// INITIALIZERS (video's values)-------------------------
var prefx = 3
var modulo = 17
// SECRET NUMBERS ---------------------------------------
var alice_secret_number = 19 // replaced 54 since there is a precision loss with it.
var bob_secret_number = 24
// PUBLIC KEYS ------------------------------------------
var public_alice = Math.pow(prefx , alice_secret_number)
var public_bob = Math.pow(prefx , bob_secret_number)
// Check potential overflow -----------------------------
console.log(public_alice , public_bob)
// Apply the modulo -------------------------------------
public_alice %= modulo
public_bob %= modulo
// Check the value again --------------------------------
console.log( public_alice , public_bob )
// Calculate the good number ------------------------------------------
var final_alice = Math.pow( public_bob , alice_secret_number ) % modulo
var final_bob = Math.pow( public_alice , bob_secret_number ) % modulo
console.log( final_alice , final_bob )
Problem
That doesn't always work. First, javascript, for example, loses precision.
So you can try with small numbers only. The speaker talks about big modulos. Even small one won't make it.
I gave you the code, which is not tailored toward performance but readability.
Could someone give me his/her opinion on what I am doing wrong?
All numbers in JavaScript are floats (actually doubles). The corresponding specification is IEEE 754. To represent an integer without loss of precision it must fit into the mantissa which is 53 bit big for 64 bit floats. You can check the maximum integer with Number.MAX_SAFE_INTEGER which is 9007199254740991. Everything beyond that loses precision.
Why is this a problem? (Most of) cryptography must be exact otherwise the secret cannot be learned. What you try to do is exponentiate and then apply the modulus, but since you do this separately, you get a very big number after exponentiation before it can be reduced through the modulus operation.
The solution is to use some kind of BigNumber library (like BigInteger) which handles all those big numbers for you. Note that there is specifically a modPow(exp, mod) function which combines those two steps and calculates the result efficiently.
Note that user secrets should be smaller than the modulus.
I have a formula that generates a random integer in a given range [x,y].
rand = Math.floor(x + Math.random()*(y-x+1));
And I would like the generated integer to have a higher chance of being close to the midrange.
Here is an interesting approach.
I am trying to adapt that solution to my problem (numbers skewed towards the midrange, not the extremities), but I am struggling with the formula.
beta = Math.sin(Math.random()*Math.PI)^2;
rand = Math.floor(x + beta*(y-x+1));
I do not understand how beta works. According to this graph wouldn't the numbers generated have a higher chance of being closer to 0.5? beta always returns the same number. Didn't I implement Math.random() properly? I swear javascript is messing with me right now.
You probably need a
beta = 4 * (rand - 0.5)^3 + 0.5
function or something with a similar shape
Graph
Distribution results: http://jsfiddle.net/4hBqz/
Okay, so I'm doing some research on how random numbers are generated with the Math.random method. So far I learned that it starts with a "random" seed, and that seed is plugged into some complex equation to create a random number. If the seed is always the same, will the outcome always be the same?
I heard that the seeds for Math.random are generated through the current time, is that correct? They must use the current time all the way down to the mili-seconds or something, because if you didn't you would get the same outcome.
What exactly is the seed? Is it the time such as "10:45" or the time AND date such as "10:45 11/8/12" or some combination?
How can I find the seed, so I can predict the output?
I want to be able to plug this:
alert(Math.floor((Math.random()*10)+1));
into my url bar, and be able to predict the result. Is that possible?
I looked through the Rhino source code to find out which pseudo-random function they use. Apparently they fall back to the Math.random function defined in the Java standard library.
The documentation for Math.random says:
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
When this method is first called, it creates a single new pseudorandom-number generator, exactly as if by the expression
new java.util.Random
This new pseudorandom-number generator is used thereafter for all calls to this method and is used nowhere else.
This method is properly synchronized to allow correct use by more than one thread. However, if many threads need to generate pseudorandom numbers at a great rate, it may reduce contention for each thread to have its own pseudorandom-number generator.
So I checked the documentation for java.util.Random and found this (for the default constructor):
Creates a new random number generator. Its seed is initialized to a value based on the current time:
public Random() { this(System.currentTimeMillis()); }
Two Random objects created within the same millisecond will have the same sequence of random numbers.
So now we know for sure that the seed is the current time in milliseconds. Also, the documentation for the second constructor says:
Creates a new random number generator using a single long seed:
public Random(long seed) { setSeed(seed); }
Used by method next to hold the state of the pseudorandom number generator.
The documentation for the setSeed method says:
Sets the seed of this random number generator using a single long seed. The general contract of setSeed is that it alters the state of this random number generator object so as to be in exactly the same state as if it had just been created with the argument seed as a seed. The method setSeed is implemented by class Random as follows:
synchronized public void setSeed(long seed) {
this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
haveNextNextGaussian = false;
}
The implementation of setSeed by class Random happens to use only 48 bits of the given seed. In general, however, an overriding method may use all 64 bits of the long argument as a seed value. Note: Although the seed value is an AtomicLong, this method must still be synchronized to ensure correct semantics of haveNextNextGaussian.
The actual method used to generate the random number is nextDouble:
Returns the next pseudorandom, uniformly distributed double value between 0.0 and 1.0 from this random number generator's sequence.
The implementation of the nextDouble function is as follows:
public double nextDouble() {
return (((long)next(26) << 27) + next(27))
/ (double)(1L << 53);
}
Clearly it depends on the next function:
Generates the next pseudorandom number. Subclass should override this, as this is used by all other methods.
The implementation of the next function is as follows:
synchronized protected int next(int bits) {
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int)(seed >>> (48 - bits));
}
That's the pseudo-random function you are looking for. As it's said in the documentation:
This is a linear congruential pseudorandom number generator, as defined by D. H. Lehmer and described by Donald E. Knuth in The Art of Computer Programming, Volume 2: Seminumerical Algorithms, section 3.2.1.
Note however that this is only the random number generator used by Rhino. Other implementations like Spidermonkey and V8 may have their own pseudo-random number generators.
it's likely that there's more to the seed than the millisecond count, because you can call Math.random() many times in the same millisecond and it will return a different value each time.
for (var i = 0; i < 3; i++) {
console.log(Math.random(), (new Date()).getTime());
};
My output:
0.0617244818713516 1352433709108
0.8024995378218591 1352433709108
0.2409922298975289 1352433709108
If I were implementing it I might make the initial seed based on a millisecond count, and then add 1 each time it's called, so that you wouldn't get the same seed value twice.
Here's a 100% accurate way of predicting the output from Math.random():
Math.random = function () { return .5; };
Now Math.random() will always return .5.
The seed is a numeric value, so my guess is that it would be what you get if you call Date.now() (or new Date().getTime() for older browsers).
However, I'm not sure when that seed is taken, or if the seed is isolated to the current page or common to the entire browser process. Predicting random numbers is supposed to be very hard or impossible, that's the whole point of them being random.
No, you cannot predict the seed, but you can preemtively generate enough numbers in order to accurately brute force a match.
Anyhow, start of by reading the wiki page on RNG's - http://en.wikipedia.org/wiki/Random_number_generation, the look at the practical implementations of PRNG's.
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.
I have used this code to exactly try to have the RGB code of color:
var huePixel = HueCanvas.css('background-color').match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);//["rgb(0, 70, 255", "0", "70", "255"]
var svPixel = SVCanvas.get(0).getContext("2d").getImageData(satPos,valPos,1,1).data;
//opacity*original + (1-opacity)*background = resulting pixel
var opacity =(svPixel[3]/255);
var r =parseInt((opacity*svPixel[0])+((1-opacity)*huePixel[1]));
var g =parseInt((opacity*svPixel[1])+((1-opacity)*huePixel[2]));
var b =parseInt((opacity*svPixel[2])+((1-opacity)*huePixel[3]));
The problem is that in some pixels , the RGB is not exactly the same . If i use Math.round than parseInt there is more problems , and more pixels have little changes than real ones.
I know that the problem is in var opacity =(svPixel[3]/255); , but i dont know how to put the equation to not have that problems.
Thanks for your attention.
I don't know the definite answer to your question (I'm not even sure I understand the question itself), but I'll take a shot.
It appears that you're trying to calculate the RGB value that you see when something else (the browser?) blends a non-opaque canvas on top of opaque background. (Are you sure this is the right thing to do at all?)
First, please don't use parseInt to round a number. It's used to parse strings and you should use it to convert huePixel[i] to an integer: parseInt(huePixel[i], 10) (note that I specify the radix explicitly to avoid numbers being parsed as octal).
To round values, you should use Math methods: Math.round (to closest integer), Math.ceil (round up) or Math.floor (round down).
Maybe the problem you're having is caused by rounding errors (hard to say without the specific inputs and expected outputs of the calculation). To minimize the rounding errors, you could try rewriting the formula like this:
(opacity * svPixel[0]) + ((1-opacity) * huePixel[1]) =
huePixel[1] + opacity * (svPixel[0]-huePixel[1]) =
huePixel[1] + svPixel[3] * (svPixel[0]-huePixel[1]) / 255