Javascript: explain this one line of code to me please - javascript

I have this simple array:
var RedirUrl = new Array(4);
RedirUrl[0] = 'http://mafi.se/mf_redir/new_install_'+this_version+'.html';
RedirUrl[1] = 'http://ifurls.com/mf_redir/new_install_'+this_version+'.html';
RedirUrl[2] = 'http://ez.se/xml-update/mf_redir/new_install_'+this_version+'.html';
RedirUrl[3] = 'http://ilovre.net/mf_redir/new_install_'+this_version+'.html';
RedirUrl[4] = 'http://rihel.com/mf_redir/new_install_'+this_version+'.html';
and then
RedirUrl.sort(function() {return 0.5 - Math.random()})
The last bit is what is confusing me.
I understand the "sort" and I understand the Math.random but the return 0.5 confuses me... what exactly is that?
(Needless to say I downloaded it off the net as it does what i want it to do... but i just dont understand it.)

It's sorting the list of URLs with a sorting method that randomly returns values that are greater than or less than 0 in about half the cases each.
Math.random() returns a number betweeen 0 and 1. Therefore 0.5 - Math.random() is a randomly decided value between -0.5 and 0.5. About half of those values are greater than zero and half of those are less than zero.
So about half of the time the comparison function will say that the first object is greater than the second and half of the time it will say the opposite.
It's a simple way to randomly shuffle the array. As has been pointed out in the comments, it's not a good way to shuffle an array (because the distribution is not even).
This question has a working implementation of the known-good Fisher-Yates shuffle.

sort() takes a function for comparing values in an array as it's argument. Here the sort() method is told to give a random number between 0.0 and 1.0, and the 0.5 is there to make the random number go between -0.5 to 0.5, this randomly saying lesser or greater than.

A comparator function should return < 0 to indicate that the first value is smaller, > 0 to indicate that it's larger, and 0 to indicate equality. Math.random() returns a number between 0 and 1. So, by doing the subtraction, you get random ordering!

This would shuffle the array. If a function is used withing Array.sort() then it usually has two parameters which are compared Array.sort(function(a,b){}). A return value less than 0 indicates that a is before b, greater than 0 that a is after b and 0 that they have the same order. Using 0.5 - Math.random() means that you should get values greater or less than 0 at random.

Seems the script will randomly shuffle this array by having the compare function randomly returns a value between -0.5 and +0.5
Also it generates an array of length 4 but then fills it with 5 items
I suggest this format instead
var RedirUrl = [
'http://mafi.se/mf_redir/new_install_'+this_version+'.html',
'http://ifurls.com/mf_redir/new_install_'+this_version+'.html',
'http://ez.se/xml-update/mf_redir/new_install_'+this_version+'.html',
'http://ilovre.net/mf_redir/new_install_'+this_version+'.html',
'http://rihel.com/mf_redir/new_install_'+this_version+'.html'
]

Here sort will be performing a sort based on the comparison function that you pass to it.
In your case, it is:
function() {return 0.5 - Math.random()}
Assuming you are familiar with comparison based sorting, the function should return a negative value indicating that the left hand side value is less, zero if they are equal and positive if left hand side value is greater than the right hand side value, much like C function strcmp().
Looking into the function that you have, it will try to perform a random sort, that is try to shuffle the array.
On an additional note, this kind of shuffling algorithm is not an ideal one. It will be self contradictory. Since everything will occur at random, it may lead to situations where say, a.

Related

Generating a random number within a large range based on probabilities

I am curious how Stake.com managed to create the game "Limbo" where the odds of a multiplier happening is specific to the probability they've calculated. Here's the game : https://stake.com/casino/games/limbo
For example :
Multiplier -> x2
Probability -> 49.5% chance.
What it means is you have a 49.5% chance of winning because those are the odds that the multiplier will actually hit a number above x2.
If you set the multiplier all the way up to x1,000,000. You have a 0.00099% chance of actually hitting 1,000,000.
It's not a project I'm working on but I'm just extremely curious how we could achieve this.
Example:
Math.floor(Math.random()*1000000)
is not as random as we think, since Math.random() generates a number between 0-1. When paired with a huge multiplier like 1,000,000. We would actually generate a 6-figure number most of the time and it's not as random as we thought.
I've read that we have to convert it into a power law distribution but I'm not sure how it works. Would love to have more material to read up on how it works.
It sounds like you need to define some function that gives the probability of winning for a given multiplier N. These probabilities don't have to add up to 1, because they are not part of the same random variable; there is a unique random variable for each N chosen and two events, win or lose; we can subscript them as win(N) and lose(N). We really only need to define win(N) since lose(N) = 1 - win(N).
Something like an exponential functional would make sense here. Consider win(N) = 2^(1 - N). Then we get the following probabilities of winning:
n win(n)
1 1
2 1/2
3 1/4
4 1/8
etc
Or we could use just an inverse function: win(N) = 1/N
n win(n)
1 1
2 1/2
3 1/3
...
Then to actually see whether you win or lose for a given N, just choose a random number in some range - [0.0, 1.0) works fine for this purpose - and see whether that number is less than the win(N). If so, it's a win, of not, it's a loss.
Yes, technically speaking, it is probably true that the floating point numbers are not really uniformly distributed over [0, 1) when calling standard library functions. If you really need that level of precision then you have a much harder problem. But, for a game, regular rand() type functions should be plenty uniform for your purposes.

What's the difference between Math.random() >= 0.5 and Math.random() - 0.5

I want to generate an array of length n, and the elements of the array are the random integer between 2 and 32. I use the function follow but I find that 17 will always be the first element of the returned array. What's more, when I change to sort function to sort(() => Math.random() - 0.5), it works well.
So I am confused that what's the difference betweenMath.random() >= 0.5 and Math.random() - 0.5? And how the difference affects the sort() function?
const fn = (n) => {
let arr = [];
for (let i = 2; i < 33; i++) {
arr.push(i);
}
return arr.sort(() => Math.random() >= 0.5).slice(0, n)
}
You're not using sort for it's intended purpose, and the results are therefore unpredictable, weird and can vary between browser implementations. If you wish to shuffle an array, here is a far better function.
The function passed into Array.sort() should accept two arguments x and y and returns a negative value if x < y, zero if x = y, or a positive value if x > y.
In your first try, you use sort(() => Math.random() >= 0.5), which returns a boolean; this is going to be cast to a 0 or a 1. This then means that your function is telling the sorter that whatever first argument you pass in is always going to be equal to or greater than whatever second argument you pass in. It just happens that 17 is passed in as the second argument every time your function is called; you tell the browser that it is therefore less than or equal to every other element in the array, and thus it will get put at the beginning of the array.
Your second attempt, with sort(() => Math.random() - 0.5), returns with equal probability that the first number is greater than the second, or vice versa, which makes the shuffle work much better. However, because of the unreliability of the whole thing there's zero assurance that the shuffle will work in all browsers or be particularly random. Please use the "real" shuffle algorithm linked above.
Source: http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.sort
For js sort, the param is the compare function, that need to be return 3 values: negative, zero, positive for less than, equal and greater than.
If you use >=, it only returns boolean.

Order of operations for Math.floor(Math.random() * 5 + 1)?

In the Code Academy JS course, Dragon Slayer 2/6, the following text is used in the hint to describe the order of operations for the code I included in the title.
How does this code work?
Math.floor(Math.random() * 5 + 1);
First we use Math.random() to create a random number from 0 up to 1. For example, 0.5
Then we multiply by 5 to make the random number from 0 up to 5. For >example, 0.5 * 5 = 2.5
Next we use Math.floor() to round down to a whole number. For example, >Math.floor( 2.5 ) = 2
Finally we add 1 to change the range from between 0 and 4 to between 1 and >5 (up to and including 5)
I've looked this up in several different places (here and here), and a majority of them either focus on the range that Math.random() produces (which I understand) or confirm the order of operations outlined in the hint, wherein "Math.floor" acts upon "Math.random()*5" prior to the "+1" being added.
It seems to me however that, according to the order of operations that I learned in school, the last two steps should be flipped. Would that not be the case since "Math.random()*5" and the "+ 1" are both within the parenthesis?
While the difference between these two might not make a difference in the value returned from this particular code, I could see a fundamental change in the order of operation like the one outlined here would cause me some frustration further down the road if I didn't know it.
Math.floor() will work on whatever is inside the brackets, after it has been calculated.
Math.floor(Math.random() * 5 + 1)
is the same as
var i = Math.random() * 5;
i += 1;
Math.floor(i);
You are correct that the wording on the page is wrong. The last thing that will happen is the floor call. Everything in the parenthesis will be processed first.
Honestly, I think they mixed up here, and you're right. According to PEMDAS and any mathematics I've ever learned, the +1 comes before the Math.floor function.
The Math.random() function returns a random number in the range [0, 1) that is, from 0 (inclusive) up to but not including 1 (exclusive). It can be any thing like 0,.34,.42 etc.
if you want random number between 0-5.
you will used Math.Random()*5. This will give you any number like 0,4.43.4.34 but not five.
Then we add 1 like this Math.random() * 5 + 1. Now the chances is you will get a number which is between 0 and 6. But you don't want number above 5. so
you apply floor method which will return largest integer less than or equal to a given number.

Confusion with combining Math.max and Math.min

There is a formula I have read on stackoverflow and one thing is not clear to me, more on that below. maxMax returns the second value within the brackets and the mathMin the first one.
So let us assume I am making a calculation where let us say:
max = 2 * 10
min = 2 * 5
In order to calculate the max and min in one line I would have to use this formula:
Math.max(a, Math.min(x, b))
The issue I am having is that math.max looks as if it returns math.min in this formula. Does that not destroy the cause of max or am I missunderstanding something?
For example in an application that strictly needs to define a min and max value for something the above formula is correct or not?
.
Math.max(a, Math.min(x, b));
Assuming a, b, and x are numbers, Math.min(x,b) is always resolved and number is returned.
Taking the result to Math.max method, action is performed and larger number is returned.
It could also be defined in 2 steps as
var min = Math.min(x, b);
Math.max(a, min);
Reading the above example should be more clear and easier to understand.
See more examples at Math.max() and Math.min()
The naming of the functions Math.min and Math.max is a bit ambiguous.
In order to clip a value to a given range you can use them like this:
clippedValue = Math.max(lowerBound, Math.min(value, upperBound))
Math.max takes an arbitrary amount of numbers and returns the biggest one while Math.min also takes an arbitrary amount of numbers and returns the smallest.
This behavior might be in contradiction to your expectations when you're looking for a way to clip values. Math.min doesn't clip a value to a minimum bound, just as Math.max doesn't clip a value to a maximum bound.
But (accidentally?) they work as desired if you change their names. So Math.max with two arguments works like a hypothetical Math.clipMin, just as Math.min with two argments works like a hypothetical Math.clipMax.

What are the chances that JavaScript Math.Random() will create the same number twice in a row?

Is this correct? using - http://en.wikipedia.org/wiki/Binomial_probability
Looks like values are from .0000000000000000 to .9999999999999999
Probability of happening twice = p^2 = (1/9999999999999999)^2 = 1.0 e-32
I think I am missing something here?
Also, how does being a pseudo random number generator change this calculation?
Thank You.
In an ideal world Math.random() would be absolutely random, with one output being completely independent from another, which (assuming p=the probability of any given number being produced) results in a probably of p^2 for any value being repeated immediately after another (as others have already said).
In practice people want Math.random to be fast which means pseudo-random number generators are used by the engines. There are many different kinds of PRNG but the most basic is a linear congruential generator, which is basically a function along the lines of:
s(n + 1) = some_prime * s(n) + some_value mod some_other_prime
If such a generator is used then you won't see a value repeated until you've called random() some_other_prime times. You're guaranteed of that.
Relatively recently however it's become apparent that this kind of behaviour (coupled with seeding the PRNGs with the current time) could be used for some forms tracking have led to browsers doing a number of things that mean you can't assume anything about subsequent random() calls.
I think the probability of getting two numbers in a row is 1 divided by the range of the generator, assuming that it has a good distribution.
The reason for this is that the first number can be anything, and the second number needs to just be that number again, which means we don't care about the first number at all. The probability of getting the same number twice in a row is the same as the probability of getting any particular number once.
Getting some particular number twice in a row, e.g. two 0.5s in a row, would be p^2; however, if you just care about any number twice in a row, it's just p.
If the numbers were truly random, you'd expect them, indeed, to appear with probability 1/p, so twice that would be 1/p^2.
The value for p is not exactly the one you have though, because the numbers are being represented internally as binary. Figure out how many bits of mantissa the numbers have in javascript and use that for your combinatoric count.
The "pseudorandom" part is more interesting, because the properties of pseudorandom number generators vary. Knuth does some lovely work with that in Seminumerical Algorithms, but basically most usual PN generators have at least some spectral distributiuon. Cryptograp0hic PN generators are generally stronger.
Update: The amount of time shouldn't be significant. Whether it's a millisecond or a year, as long as you don't update the state The probabilities will stay the same.
The probability that you would get 2 given numbers is (1/p)^2, but the probability that you get 2 of same numbers (any) is 1/p. That is because the first number can be anything, and the second just needs to match that.
You can kind of find out, just let it run a few days :)
var last = 0.1;
var count = 0 | 0;
function rand(){
++count;
var num = Math.random();
if(num === last){
console.log('count: '+count+' num: '+num);
}
last = num;
}
while(true) rand();

Categories