JavaScript Random Number [duplicate] - javascript

This question already has answers here:
Generating random whole numbers in JavaScript in a specific range
(39 answers)
Closed 9 years ago.
This maybe more mathematical question than programming. In JS I wanted to a function that returns a random integer number in an interval lets say 1-6 and this is what I found:
// Returns a random integer between min and max
// Using Math.round() will give you a non-uniform distribution!
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
I feel guilty if I copy and paste this in my code. I don't understand this :
Why we subtract min from max, add 1, multiply the answer by Math.random() and then add the min. I tired with several numbers manually on paper and it work just fine ! But I don't understand why !

Assuming you already understand the behaviour of Math.floor and Math.random, here's the rest step by step:
Math.random() ↝ a random number between 0 (inclusive) and 1 (exclusive)
Math.random() * max ↝ a random number between 0 (inclusive) and max (exclusive)
Math.floor(Math.random() * max) ↝ a random integer between 0 (incl.) and max (excl.)
Math.floor(Math.random() * (max - min)) + min ↝ a random integer between min (incl.) and max (excl.)
Math.floor(Math.random() * ((max + 1) - min)) + min ↝ a random integer between min (incl.) and max+1 (excl.) (OR between min and max both inclusive)

Math.random() will give you a "real" number from 0 to 1 (not including 1.0).
That's cool and all, but what if I want a "real" number from 1 to 2?
The answer: "transform" your [0,1) into [1,2).
In practical terms, it means adding 1 to your result.
Try it out -- Math.random()+1 will give you a number from 1 to 2.
In mathematics this is known as a "mapping". That is -- for every possible real number in [0,1), find a way to "map" that real number to another real number in [1,2). That is, if I give you any real number between [0,1), you should be able to map that number -- apply that number to a function that will return a number between [1,2).
In our case, that function f(x) = x+1.
Do you see how this gives us random numbers between [1,2)? Visualize the two intervals next to each other and imagine a line going from every point in [0,1) to its corresponding map in [1,2). Now, pick a random point on [0,1) ... and follow the line. You'll follow the line to a random point in [1,2)!
Now, all complete one-to-one maps from [0,1) to [1,2) will turn a random number between [0,1) to a random number between [1,2)...but not all of them will give you an evenly distributed random number between [1,2). The mathematics behind what maps give you evenly distributed results is a bit complicated but in short, if your map only involves adding, subtracting, multiplying, and dividing by constants, it's "legal" in the sense that the results will also be evenly distributed.
So, now we know how to transform [0,1) into [1,2).
What if I want to map [0,1) onto [0,2)? I can't just add numbers anymore ...
How about I multiply everything by two?
This should work -- the function f(x) = x*2 does indeed map every point on [0,1) to a point on [0,2) --- and because it only involves multiplication by constants (2), it is a distribution-preserving map.
This works! Math.random()*2 will give you a random number between 0 and 2.
Okay, now something a bit more complicated ... transforming [0,1) into [1,3).
Multiplying by two doesn't work ... 0*2 = 0, and that's not in your target range.
Adding one doesn't work... even though 0+1 is in your target range and 1+1 is, as well, there is no way you can ever reach 3.
If we can't transform [0,1) into [1,3), let's try and see if we can transform something else into [1,3).
How about [0,2)? Yes, we can do this ... the function f(x) = x+1 perfectly maps [0,2) to [1,3). You can think of + as "shifting" the range up.
And so the solution here is clear -- first, turn [0,1) into [0,2), then turn [0,2) into [1,3).
We already know the first (f(x) = x*2), and we figured out the second (f(x) = x+1). So the "combined" transformation/map is f(x) = (x*2)+1.
That is, Math.random()*2 + 1 will give you a number from 0 to 3.
Now for the final trick...mapping [0,1) to an arbitrary range [min,max).
The secret here is to re-write this as [min,min+range), where range = max-min.
Here you can see that it's simple to transform the range [0,range) to [min,min+range) -- you just add "min" to it. So if I had the range [0,range), and I wanted to get [min,min+range), i would use f(x) = x+min.
So how do we get from [0,1) to [0,range) ?
Multiply by range!
f(x) = (x*range) + min
Now writing things back to original terms, using range = max-min
f(x) = (x*(max-min)) + min
will transform a real number from [0,1) to a real number from [min,max)
I'll leave the rest (turning it into a useful integer) to you

0 <= Math.random() < 1 =>
0 <= Math.random() * 6 < 6 =>
0 <= Math.floor( Math.random() * 6 ) <= 5
then you add 'min' so it would look like this:
min <= Math.floor( Math.random() * 6 ) <= 5 + min
in your exemple, for min = 1 you will have all the numbers in 1-6.
I hope now is much clear.

Here's an explanation of your code:
Math.random() generates a random number between 0 and 1 (not including 1).
You need to scale that value based on the range of numbers you want. Your range is how far from your min desired number to your max desired number which is max - min.
If you want to include the max value in the range of numbers generated, then use max - min + 1
You then need to make sure the random number starts at the right base rather than 0 so you add min to it.
Then, if you want it to be an integer you call Math.floor() to truncate it to the next lowest integer.
So, if you just had this:
Math.floor(Math.random())
You would always get zero. Because Math.floor() of a float value between 0 and 1 (not including one) will always truncate down to 0.
Then, if you expand the range with:
Math.floor(Math.random() * (max - min + 1))
You would now get a random number between 0 and max - min including the larger value.
So, to then get it to start at the right base, you add in min like this:
Math.floor(Math.random() * (max - min + 1)) + min

Related

What will Math.floor(Math.random() * 10 + 1); do [duplicate]

This question already has answers here:
Generating random whole numbers in JavaScript in a specific range
(40 answers)
How does Math.floor(Math.random() * (Max - Min + 1) + Min) work in JavaScript? (Theory)
(3 answers)
Closed 8 months ago.
I came across the following command:
Math.floor(Math.random() * 10 + 1);
I understand that Math.floor() will convert to the lowest integer, but what does Math.random() * 10 + 1 do?
Math.random returns a floating point number x such that:
Multiplying 10 to x yields a floating point number in the range:
And then adding 1 to 10x yields a floating point number in the range:
And finally flooring 10x + 1 yields an integer in the range:
Therefore, Math.floor(Math.random() * 10 + 1) yields an integer that lies in the range [1, 10].
Math.random generates a random number between 0 and 1. So for example it can be .124 or .42242. When you multiply this random number against something, you are basically making it so that the new result is no less than 0, but no more than the number you are multiplying it against.
So in your example, you are multiplying it against 10, which means you will get a random number between 0 and 10 with decimals; technically this range is 'more than 0, but less than 10'. The +1 just increases the total range so that it is between 1 and 11, or 'more than 1, but less than 11.
When you apply Math.floor() to this, you are rounding all of these results down. So in the case without the '+1', your finite range is actually 0-9, and with the +1 it is 1-10

Random number generator doesn't produce expected numbers within a given range using values from input fields [duplicate]

This question already has answers here:
Generate random number between two numbers in JavaScript
(32 answers)
Closed 3 years ago.
I'm trying to generate a random number between two given values. I'm able to produce this with a pretty standard little function, however when I try to set the maximum and minimum values through an input field, I get some unexpected results.
This is using jQuery, which isn't necessary for this particular function but is needed for the larger project.
Here's an example of what I'm finding:
https://jsfiddle.net/u2k41hzd/
function randomNumber(min, max) {
points = Math.floor(Math.random() * (max - min + 1) + min);
}
$( "button" ).on( "click", function ( event ) {
minPoints = $( ".min-points" ).val();
maxPoints = $( ".max-points" ).val();
randomNumber(minPoints, maxPoints);
$(".random").html(points);
});
In the case of the minimum number being 1 and the maximum being 6, I would expect to get numbers between 1 and 6. However, I get numbers between 0 and 5.
If the minimum number is 2 and the maximum 6, I would expect to get numbers between 2 and 6, but get numbers between 0 and 4. Passing in 3 and 6 gives numbers between 0 and 3, and so on.
Ignoring the input values and hard coding them instead seems produce expected results with no issue. Essentially I'm just unsure as to why the input values are behaving as they are. I'm sure I've just misunderstood something or made a mistake somewhere, but I've not been able to determine the reason!
The issue is that you need to add the min to the rounded number, not to the randomly generated number:
function randomNumber(min, max) {
points = Math.floor(Math.random() * (max - min + 1)) + min;
}
To explain further, for the case of 2 and 9:
Math.random() generates a number between 0 and 0.999999999...
max - min + 1 = 8
So the generated number will be in the range 8 * 0 and 8 * 0.99999999...
Flooring it will round down in the range [0, 7]
The result would need to be offset by the starting number (i.e. the minimum allowed number - 2)

How can I generate a random number between 1 and 2,147,483,647 [duplicate]

This question already has answers here:
Generating random whole numbers in JavaScript in a specific range
(39 answers)
Closed 6 years ago.
I know about random that generates a random number between 0 and 1.
Math.random();
But how can I generate a random number between 1 and 2,147,483,647 using Javascript?
You can simply multiply Math.random() times the limit value and then round down. Since Math.random() returns a decimal value between 0 and 1, you will always get some scaled proportion of your limit value so your result will be between 0 and your limit value.
If you want the result to be an integer, then use can call Math.floor() on the result of the multiplication to round down to an integer.
Since you also want the lowest value to be 1 instead of 0 and you want the result to include the limit value, then you can add 1 to the result to put it in the exact range.
var maxInt = 2147483647; // max 32-bit signed int
function randomInt() {
// generate random value between 1 and maxInt inclusive of both values
return Math.floor(Math.random() * maxInt) + 1;
}
Working demo: https://jsfiddle.net/jfriend00/ntkokacf/
In order to find a number you can do something to the effect of:
var randomNumber = Math.floor(Math.random() * 2147483647);
You can also write a function to repeat that and that will allow for any minimum or maximum:
function random(min, max) {
return min + Math.floor(Math.random() * (max - min + 1));
}
The explanation of the function is that it asks for a minimum and a maximum number. Whatever the minimum number is, we add to the second half of the return statement. The second half needs to give us the number of different possible numbers between min and max, so we multiply Math.random() by that exact number, which is the difference between max and min plus one. The problem is that this gives a decimal, therefore we take the floor of that to get rid of the decimal.

Calculating percentage with min-max in Gamemaker

I have a healthbar that i want to use a min/max and actual number.
6 is min
8 is max
the actual number will float between them with 7 as the beginning number.
tried ((max_n + min_n) / act_n)*100, but of course that doesn't work.
i think i was sick that day when they went over that in school (eyeroll)
If you have a floating point value that is (6, 8) and you want the distance between the value and minimum expressed as a different between the maximum -
var min = 6,
max = 8,
current = 7,
difference = max - min,
percent = (current - min) / difference; // <-- is the value you're after
// it is 50% between (6,8)
I'm not sure I understand what you're doing, but I believe you're calculating the average the wrong way.
Shouldn't you have the actual value be divided by the total possible?
Currently, your logic looks like this:
(8 + 6 (14) / Actual (7) )*100, which would be 14/7 = 2 * 100 = 200.
I think you need to reverse these two arguments, the min+max and the actual value.
If it were me, instead of doing it that way, I would actually subtract the minimum amount from both, and then divide it by the difference between the two.
If the 6 and 8 are dynamic, this may look like:
( (act_n - min_n) / (max_n - min_n) )*100
Or, with values, that would be:
( (7.2 - 6) / (8 - 6)*100
(1.2 / 2)*100 = 60, so your percentage would be 60%
I don't use Javascript, so please ignore any spacing errors I made. I don't know how strict the language is.

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