In a software I am working on (sensor simulation), I needed to generate normally distributed noise for simulated sensor signals. I used the central limit theorem. I generated 20 random numbers and built an average out of them to approximate the gaussian distribution.
So I took the "measured" signal and generated 20 numbers from -noiseMax to +noiseMax and averaged them. I added the result to the signal to have noise.
Now, for my university, I have to describe this Gaussian distribution by its mean and variance. Ok, mean will be 0 but I have absolutely no idea how to convert noiseMax in my program into the variance. Googling haven't helped much.
I was not sure if SO is the right SE platform for this question. Sorry if it isn't.
OK, so the central limit theorem says that the average of a sufficiently large number of uniformally distributed variables will be normal. In the statistics classes I have taken, 30 is usually used as the cutoff, so you might want to increase your simulation's "sample size".
However, you can find the Standard Deviation of your average as follows regardless of "sample size".
The standard deviation of your uniform variable is (b-a)/sqrt(12)== noiseMax/sqrt(3).
Variances add when you add variables, so the standard deviation of n the sum of n of these variables is sqrt(n*(noiseMax/sqrt(3))*(noiseMax/sqrt(3)))==noiseMax*sqrt(n/3).
Dividing by n to get the average gives you a final standard deviation of noiseMax/sqrt(3*n). In your case, sigma = noiseMax * 0.12909944487.
From theoretical POV this is known as Irwin-Hall distribution
Simplest to produce N(0,1) is sum of 12 uniform RN minus 6, no need for scaling
In general, to see how variance is computed, take a look at
http://en.wikipedia.org/wiki/Irwin%E2%80%93Hall_distribution
I would also recommend to look at the Table of Numerical Values in the following article: http://en.wikipedia.org/wiki/68%E2%80%9395%E2%80%9399.7_rule.
For example, if one to use sum of 12 uniform numbers (minus 6), then min value would be at -6 (exactly -6*sigma) and max value would be at +6 (exactly +6*sigma). Looking at the table, what would be expected frequency outside the range? Answer: 1/506797346. Thus, one out of ~half a billion events shall land outside the +-6sigma, but Irwill-Hall(12) rng will miss it. Thus, you could judge if it is ok or not for your particular simulation
Related
I have this simple test in nodejs, I left it running overnight and could not get Math.random() to repeat. I realize that sooner or later the values (or even the whole sequence) will repeat, but is there any reasonable expectancy as to when it is going to happen?
let v = {};
for (let i = 0;; i++) {
let r = Math.random();
if (r in v) break;
v[r] = r;
}
console.log(i);
It is browser specific:
https://www.ecma-international.org/ecma-262/6.0/#sec-math.random
20.2.2.27
Math.random ( ) Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo
randomly with approximately uniform distribution over that range,
using an implementation-dependent algorithm or strategy. This function
takes no arguments.
Each Math.random function created for distinct code Realms must
produce a distinct sequence of values from successive calls.
The requirement here is just pseudo-random with uniform distribution.
Here's a blog post from V8 (Chrome and NodeJs's Javascript Engine).
https://v8.dev/blog/math-random
Where they say they are using xorshift128+, which has a maximal period of 2^128 -1.
Related (on another site): Acceptable to rely on random ints being unique?
Also extremely related: How many double numbers are there between 0.0 and 1.0?
Mathematically, there are an infinite number of real numbers between 0 and 1. However, there are only a finite number of possible values that Math.Random could generate (because computers only have a finite number of bits to represent numbers). Let's say that there are N possible values that it could generate. Then, by the Pigeonhole Principle, there is a 100% chance of getting at least one duplicate value once you generate exactly N + 1 values.
At this point, the Birthday Paradox demonstrates that you should start seeing duplicates surprisingly quickly. According to this "paradox" (which isn't a true paradox, just counterintuitive), given a room with only 23 people, there's a greater than 50% chance of two of them having the same birthday.
Returning to our example, the rule of thumb for calculating this (see the linked Wikipedia article) suggests that Math.Random reaches a 50% probability of duplicates once you generate approximately sqrt(N) numbers.
From the linked Stack Overflow question, if we assume that there are 7,036,874,417,766 numbers between 0 and 1 like the accepted answer says (and please read the linked question for a more detailed explanation of how many there actually are), then sqrt(7036874417766) is just over 2.652 million, which isn't actually all that many. If you are generating 10,000 random numbers per second, you'd reach 50% probability in approximately 737 hours, which is just under 31 days. Less fortunately, even at 10,000 per second, it would take approximately 195,468 hours (which is approximately 22.3 years) to reach 100% probability.
Some of the other answers give much higher figures for how many numbers there are, so take your pick.
First note that mod(3^146,293)=292. For some reason, inputting mod(3^146,293) in Matlab returns 275. Inputting Math.pow(3,146) % 293 in JS returns 275. This same error occurs (as far as I can tell) every time. This leads me to believe I am missing something obvious but cannot seem to tell what.
Any help is much appreciated.
As discussed in the answers to this related question, MATLAB uses double-precision floating point numbers by default, which have limits on their resolution (i.e. the floating point relative accuracy, eps). For example:
>> a = 3^146
a =
4.567759074507741e+69
>> eps(a)
ans =
7.662477704329444e+53
In this case, 3146 is on the order of 1069 and the relative accuracy is on the order of 1053. With only 16 digits of precision, a double can't store the exact integer representation of an arbitrary 70 digit integer.
An alternative in MATLAB is to use the Symbolic Toolbox to create symbolic numbers with a greater resolution. This gives you the answer you expect:
>> a = sym('3^146')
a =
4567759074507740406477787437675267212178680251724974985372646979033929
>> mod(a, 293)
ans =
292
Math.pow(3, 146) is is larger than the constant Number.MAX_SAFE_INTEGER in JavaScript which represents the upper limit of numbers that can be represented without losing any accuracy. Therefore JavaScript cannot accurately represent Math.pow(3, 146) within the 64 bit limit.
MatLab also has limits on its integer size but can represent a large number with the Symbolic Math Toolbox.
There are also algorithms that you can implement to accomplish this without overflowing.
StackOverflow warns me that I may be down-voted for this question, but I'd appreciate your not doing so, as I post this simply to try to understand a programming exercise I've been posed with, and over which I've been puzzling a while now.
I'm doing some javascript coding exercises and one of the assignments was to devise an "encryption function", encipher, which would encrypt a 4-digit number by multiplying it by a number sufficiently low such that none of its digits exceeds 9, so that a 4-digit number is returned. Thus
encipher(0204)
might yield
0408
where the multiplier would have been 2. -- This is very basic material, simply to practice the Javascript. -- But as far as I can see, the numbers returned can never be deciphered (which is the next part of the exercise). Even if you store a dictionary internal to encipher, along the lines of
{'0408':'2'}, etc
so that you could do a lookup on 0408 and return 0204, these entries could not be assured to be unique. If one for example were to get the number 9999 to be deciphered, one would never know whether the original number was 9999 (multiplied by 1), 3333 (multiplied by 3) or 1111 (multiplied by 9). Is that correct? I realise this is a fairly silly and artificial problem, but I'm trying to understand if the instructions to the exercise are not quite right, or if I'm missing something. Here is the original problem:
Now, let's add one more level of security. After changing the position of the digits, we will multiply each member by a number whose multiplication does not exceed 10. (If it is higher than 10, we will get a two-digit multiplication and the code will no longer be 4 values). Now, implement in another function the decrypter (), which will receive as an argument an encrypted code (and correspondingly multiplied in the section above and return the decrypted code.
Leaving the exercise behind, I'm just curious whether there exists any way to "encrypt" (when I say "encrypt", I mean at a moderate javascript level, as I'm not a cryptography expert) an n-digit number and return a unique n-digit number?
Thanks for any insights. --
encrypt a 4-digit number by multiplying it by a number sufficiently low such that none of its digits exceeds 9, so that a 4-digit number is returned
If your input is 9999, there is no integer other than 1 or 0 that you can multiply your input by and get a positive number with a maximum of 4 digits. Therefore, there is no solution that involves only integer multiplication. However, integer multiplication can be used as part of an algorithm such as rotating digits (see below).
If instead you're looking for some sort of bijective algorithm (one that uniquely maps A to B and B to A), you can look at something like rotating the digits left or right, reversing the order of the digits, or using a unique mapping of each individual digit to another. Those can also be mixed.
Examples
Rotate
1234 -> 2341
Reverse
1234 -> 4321
Remap digits e.g. 2 mapped to 8, 3 mapped to 1
2323 -> 8181
Note that none of these are cryptographically sound methods to encrypt information, but they do seem to more-or-less meet the objectives of the exercise.
This may look more like a math question but as it is exclusively linked to Javascript's pseudo-random number generator I guess it is a good fit for SO. If not, feel free to move it elsewhere.
First off, I'm aware that ES does not specify the algorithm to be used in the pseudo-random number generator - Math.random() -, but it does specify that the range should have an approximate uniform distribution:
15.8.2.14 random ( )
Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an implementation-dependent algorithm or strategy. This function takes no arguments.
So far, so good. Now I've recently stumbled upon this piece of data from MDN:
Note that as numbers in JavaScript are IEEE 754 floating point numbers with round-to-nearest-even behavior, these ranges, excluding the one for Math.random() itself, aren't exact, and depending on the bounds it's possible in extremely rare cases (on the order of 1 in 2^62) to calculate the usually-excluded upper bound.
Okay. It led me to some testing, the results are (obviously) the same on Chrome console and Firefox's Firebug:
>> 0.99999999999999995
1
>> 0.999999999999999945
1
>> 0.999999999999999944
0.9999999999999999
Let's put it in a simple practical example to make my question more clear:
Math.floor(Math.random() * 1)
Considering the code above, IEEE 754 floating point numbers with round-to-nearest-even behavior, under the assessment of Math.random() range being evenly distributed, I concluded that the odds for it to return the usually excluded upper bound (1 in my code above) would be 0.000000000000000055555..., that is approximately 1/18,000,000,000,000,000.
Looking at the MDN number now, 1/2^62 evaluates to 1/4,611,686,018,427,387,904, that is, over 200 times smaller than the result from my calc.
Am I doing the wrong math? Is Firefox's pseudo-random number generator just not evenly distributed enough as to generate this 200 times difference?
I know how to work around this and I'm aware that such small odds shouldn't even be considered for every day's uses, but I'd love to understand what is going on here and if my math is broken or Mozilla's (I hope it is former). =] Any input is appreciated.
You should not be worried about rounding the number from Math.random() up to 1.
When I was looking at the implementation (inferred from results I am getting) in the current versions of IE, Chrome, and FF, there are several observations that almost certainly mean that you should always get a number in the interval 0 to 0.11111111111111111111111111111111111111111111111111111 in binary (which is 0.999999999999999944.toString(2) and a few smaller decimal numbers too btw.).
Chrome: Here it is simple. It generates numbers by generating 32 bit number and dividing it by 1 << 32. (You can see that (1 << 30) * 4 * Math.random() always return a whole number).
FF: Here it seems that the number is always generated to be at most the 0.11... (53x 1) and it really uses just those 53 decimal places. (You can see that Math.random().toString(2).length - 2 does not return more than 53).
IE: Here it is very similar to FF, except that the number of places can be more if the first digits after a decimal dot are 0 and those will not round to 1 for sure. (You can see that Math.random().toString(2).match(/1[01]*$/)[0].length does not return more than 53).
I think (although I cannot provide any proof now) that any implementation should fall to one of those described groups and have no problem with rounding to 1.
Given a five dimensional space, I would like to generate 100 vectors, all with a fixed magnitude=M, where the components values are randomly distributed.
I was originally thinking of starting off with a unit vector and then applying a rotation matrix, with random parameters for the 10 degrees of freedom ... Would this work? and how?
Any nice way of doing this in Javascript...?
cheers for any pointers!
Here is the Monte Carlo algorithm that I would use (I do not know Javascript well enough to code in it off the top of my head):
Generate random values in the range from -1 to 1 for each of the five dimensions.
Calculate the Magnitude M, if M=0 or M>1 then reject these values and return to step #1.
Normalize the vector to have a Magnitude of 1 (divide each dimension by M).
That should give you random unit vectors evenly distributed over the 5-dimensional super-sphere surface.
The question has been asked: "Why reject the vector if M>1?"
Answer: So that the final vectors will be uniformly distributed across the surface of the unit 5-sphere.
Reasoning: What we are generating in the first step is a set of random vectors that are uniformly distributed within the volume of the unit 5-cube. Some of those vectors are also within the volume of the unit 5-sphere and some of them are outside of that volume. If normalized, the vectors within the 5-sphere are evenly distributed across its surface, however, the ones outside it are not at all evenly distributed.
Think about it like this: Just as with a normal 3-dimensional Unit Cube and Unit Sphere, or even the Unit Square and the Unit Circle, the Unit 5-Sphere is wholly contained within the Unit 5-Cube, which touches only at the five positive unit dimension axis points:
(1,0,0,0,0)
(0,1,0,0,0)
(0,0,1,0,0)
(0,0,0,1,0)
(0,0,0,0,1)
and their corresponding negative unit axis points. This is because these are the only points on the surface of the cube that have a magnitude (distance from the origin) of 1, at all other points, the 5-cube's surface has a distance from the origin that is greater than 1.
And this means that there are many more points between (0,0,0,0,0) and (1,1,1,1,1) than there are between (0,0,0,0,0) and (1,0,0,0,0). In fact about SQRT(5) or aprx. 2.25 times more.
And that means that if you included all of the vectors in the unit 5-cube, you would end up with more than twice as many results "randomly" mapping to about (0.44,0.44,0.44,0.44,0.44) than to (1,0,0,0,0).
For those who are challenging (without foundation, IMHO) that this results in a uniform distribution across the surface of the 5-D Sphere, please see the alternative method in this Wikipedia article section: https://en.wikipedia.org/wiki/N-sphere#Uniformly_at_random_on_the_(n_%E2%88%92_1)-sphere
The problem with sampling from a unit hypercube in 5-dimeensions and then re-scaling, is points in some directions (towards the corners of the hypercube) will be over sampled.
But if you use a rejection scheme, then you lose too many samples. That is, the volume of a unit hypercube in 5-d is pi^2*(8/15) = 5.26378901391432. Compare that to the volume of a unit hyper-cube in 5 dimensions that will just contain the sphere. That hypercube has volume 32. So if you reject points falling outside the sphere, you will reject
1 - 5.26378901391432/32 = 0.835506593315178
or roughly 83.5% of the points get rejected. That means you will need to sample roughly 6 points on average before you do find a sample that is inside the 5-sphere.
A far better idea is to sample using a unit normal sample, then rescale that vector of points to have unit norm. Since the multi-variate normal distribution is spherically symmetric, there is no need for rejection at all.
Here are some approaches, it is for unit vectors but you can just multiply by M:
http://burtleburtle.net/bob/rand/unitvec.html
I'd recommend assigning random numbers between -1 and +1 for each element. Once all elements for a vector have been assigned, then you should normalize the vector. To normalize, simply divide each element by the magnitude of the overall vector. Once you've done that, you've got a random vector with a magnitude of 1. If you want to scale the vectors to magnitude M, you just need to multiply each element by M.
Picking without rejections (6 times faster)
From Mathworld and a link posted by Bitwise:
If you choose n numbers with a normal distribution, treat those as coordinates, and normalize the resulting vector into a unit vector, this chooses a uniformly distributed unit vector in n dimensions. - Burtleburtle (ht Bitwise)
As Bitwise points out, that should be multiplied by the desired magnitude.
Note that there is no rejection step here; the distributions themselves have dealt with the necessary bias towards zero. Since the normal distribution and a semi-circle are not the same shape, I wonder if RBarryYoung's answer really gives a uniform distribution on the surface of the sphere or not.
Regarding uniform hypercube picking with hypersphere rejection (RBarryYoung's answer)
The Mathworld article includes a description of using 4 random numbers picked from uniform distributions to calculate random vectors on the surface of a 3d sphere. It performs rejection on the 4d vector of random numbers of anything outside the unit hypersphere, as RBarryYoung does, but it differs in that it (a)uses an extra random number and (b)performs a non-linear transform on the numbers to extract the 3d unit vector.
To me, that implies that uniform distributions on each axis with hypersphere rejection will not achieve a uniform distribution over the surface of the sphere.