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.
Related
I just saw javascript code about sorting which uses setTimeout as shown
var list = [2, 5, 10, 4, 8, 32];
var result = [];
list.forEach( n => setTimeout(() => result.push(n), n));
It is interesting because in js setTimeout is asynchronous so if you wait for sufficient time, result will be sorted array. It is deterministic depends on only values of data but not the size of the input so I have no idea how to determine Big-O (time complexity) of this approach.
TLDR; it depends on how you define the complexity of setTimeout()
When discussing algorithmic complexity, we have to answer the following questions:
What are my inputs?
What is a unit of work in the hypothetical machine that my algorithm runs in?
In some cases, how we define our inputs is dependent on what the algorithm is doing and how we defined our unit of work. The problem is complicated when using built-in functions as we have to define the complexity of those functions so we can take them into account and calculate the overall complexity of the algorithm.
What is the complexity of setTimeout()? That's up for interpretation. I find it helpful to give setTimeout() a complexity of O(n), where n is the number of milliseconds passed to the function. In this case I've decided that each millisecond that is counted internally by setTimeout() represents one unit of work.
Given that setTimeout() has complexity O(n), we must now determine how it fits into the rest of our algorithm. Because we are looping through list and calling setTimeout() for each member of the list, we multiply n with another variable, let's call it k to represent the size of the list.
Putting it all together, the algorithm has complexity O(k * n), where k is the length of the numbers given, and n is the maximum value in the list.
Does this complexity make sense? Let's do a sanity check by interpreting the results of our analysis:
Our algorithm takes longer as we give it more numbers ✓
Our algorithm takes longer as we give it larger numbers ✓
Notice that the key to this conclusion was determining the complexity of setTimeout(). Had we given it a constant O(1) complexity, our end result would have been O(k), which IMO is misleading.
Edit:
Perhaps a more correct interpretation of setTimeout()'s contribution to our complexity is O(n) for all inputs, where n is the maximum value of a given list, regardless of how many times it is called.
In the original post, I made the assumption that setTimeout() would run n times for each item in the list, but this logic is slightly flawed as setTimeout() conceptually "caches" previous values, so if it is called with setTimeout(30), setTimeout(50), and setTimeout(100), it will run 100 units of work (as opposed to 180 units of work, which was the case in the original post).
Given this new "cached" interpretation of setTimeout(), the complexity is O(k + n), where k is the length of the list, and n is the maximum value in the list.
Fun fact:
This happens to have the same complexity as Counting Sort, whose complexity is also a function of list size and max list value
Let me be brief. I'm trying to calculate
alert((Math.pow(7,35))%71)
but it gives me 61, when the result must be 70. What's wrong?
As others mentioned before with regards to using Math.pow(7,35), this resulting number is way too big for Javascript to handle.
To resolve your problem you need to use an external javascript library.
(Or write your own ;) )
Here are some examples of Javascript libraries that handle big numbers.
BigNum
Bignumber
I hope it helps.
The number you're using is too big for javascript. The max size of an int is 2^53 -- which is less than 7^35.
The only value which requires more precision is an intermediate result. So the problem can also be avoided without the need for higher precision variables when you have an algorithm that doesn't need the problematic intermediate result.
The following formula can be useful for that:
(a.b) % c = (a % c)(b % c) % c
This means Math.pow(7,35)%71 = ((Math.pow(7,17)%71) * (Math.pow(7,18)%71)) % 71.
Now the intermediate results are smaller, but might still be too big. So we need to split up further and to apply the modula operator on smaller intermediate results.
So you can do something like this:
Math.pow((Math.pow(7,7)%71),5)%71
But you probably need to do this for integer numbers wich are variable (otherwise, you could have avoided the problem by hardcoding the result).
So, you need to have an idea about the range of values you can expect and to define an algoritm that splits up the power calculation into pieces that will always have results that are small enough when the input is within the expected range.
And whatever you choose for a calculation like this, calculation with higher precision variables (using a specialized library) or a specilized algoritm, you should always assert the input to make sure your calculation returns a value only when you are sure it can deliver a correct value. Otherwise your implementation becomes unreliable for anyone who isn't aware of the range in which it is valid. Otherwise return an exception with a message that tells clearly which input or combination of inputs is the problem and why.
This code snippet is from w3schools JavaScript section. I am trying to figure out what
points.sort( function(a, b) {
return 0.5 - Math.random()
});
from the code below does. I understand it is trying to perform a random sort on the numbers stored in the array called points, but I don't understand how it is achieved with return 0.5 - Math.random().
I know that random returns a number between 0 and 1 (not including 1).
I supposed that 0.5 is then subtracted from that number, but I am not sure what happens from here. Could you kindly give me a step by step explanation?
<!DOCTYPE html>
<html>
<body>
<p>Click the button (again and again) to sort the array in random order.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
var points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo").innerHTML = points;
function myFunction() {
points.sort(function(a, b){return 0.5 - Math.random()});
document.getElementById("demo").innerHTML = points;
}
</script>
</body>
Passing a callback to Array#sort() that returns a random value is a bad idea; the ECMAScript spec provides no guarantees about what will happen in that case. Per MDN:
compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.
And per the spec itself:
If comparefn is not undefined and is not a consistent comparison function for the elements of this array (see below), the sort order is implementation-defined.
The W3Schools code from the question is demonstrably broken; it doesn't shuffle the array fairly, at least in Chrome. Let's try running it a million times and counting how often each value shows up in the final position in the array after "shuffling":
function shuffleAndTakeLastElement() {
var points = [40, 100, 1, 5, 25, 10];
return points.sort(function(a, b){return 0.5 - Math.random()})[5];
}
results = {};
for (var point of [40, 100, 1, 5, 25, 10]) results[point] = 0;
for (var i = 0; i < 1000000; i++) results[shuffleAndTakeLastElement()]++;
console.log(results);
I get the following counts in Chrome:
{1: 62622, 5: 125160, 10: 500667, 25: 249340, 40: 31057, 100: 31154}
Notice how the number 10 is around 16 times more likely to end up in the end position of the array than the numbers 40 or 100 are. This ain't a fair shuffle!
A few morals to draw from this story:
You should run a large number of tests and look at the results to help confirm whether any randomness algorithm is fair.
It's easy to accidentally write a biased algorithm even if you're starting with a fair source of randomness.
For shuffling arrays, use Lodash's _.shuffle method or one of the approaches from How to randomize (shuffle) a JavaScript array?.
Never trust anything you read on W3Schools, because they suck and are riddled with errors.
The sort callback is supposed to return a value <0, 0 or >0 to indicate whether the first value is lower than, equal to or higher than the second; sort uses that to sort the values. 0.5 - Math.random() returns a value between -0.5 and 0.5 randomly, satisfying the expected return values and resulting in an essentially randomly shuffled array.
Note that this shouldn't be the preferred method to shuffle; since the return value is random and not internally consistent (e.g. it tells sort that foo < bar, bar < baz and foo > baz), it may make Javascript's sort algorithm very inefficient. A Fisher-Yates shuffle for instance is pretty trivially implemented and likely more efficient.
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.
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.