Why is [1,2,3] <= [1,2,3] true in javascript? [duplicate] - javascript

I'm trying to compare two arrays in javascript.
What I'd like is:
a < b &iff; ∃ i ≥ 0 s.t. a[i] < b[i] and ∀ 0 ≤ j < i, a[j] = b[j]
So arrays of non-negative numbers work as desired:
firebug> [0,1,2,3,4] < [1,0,0]
true
And comparing negative numbers with zero works as expected:
firebug> [-1, 1] < [0, 0]
true
But comparing negative numbers with negative numbers is... suprising:
firebug> [-2] < [-1]
false
firebug> -2 < -1
true
What's going on here, so I can correct my intuition for what array comparison means in javascript?

The array is converted to a string, which comes down to .join(), which in turn joins the elements with a comma (,) as delimiter.
"-1,1" < "0,0" === true
because the character code of - (45) is smaller than the character code of 0 (48).
On the other hand,
"-2" < "-1" === false
because the second character codes are compared (the first are both -, so that doesn't give a result yet), and the character code for 2 (50) is bigger than the character code of 1 (49), so this yields false.
It comes down to a lexographical sorting (i.e. by character codes) and not a numerical one, even if the elements are numbers (because of the string coercion).
Basically comparing arrays is not recommended. It is implicitly defined as string comparison, but this can yield surprising results.

There's no such thing as JavaScript array comparison in any form similar to what you describe.
What's happening in all cases is that your arrays are being converted first to strings by joining their contents together. Thus, the string "-2" is not less than the string "-1", because the character "2" comes after "1" in the character set. Similarly, "-1,1" is less than "0,0" because the "-" character comes before the digits.
You can see for yourself that in all cases your comparisons:
array1 < array2
get exactly the same results as:
("" + array1) < ("" + array2)
or:
array1.join(",") < array2.join(",")

I couldn't find an answer about how to actually compare arrays in Javascript and get "expected" results, so here is the code
compareArrays = function(a, b) {
var elA, elB, i, len;
for (i = 0, len = Math.min(a.length, b.length); i < len; i++) {
elA = a[i], elB = b[i];
if (elA > elB) return 1;
if (elA < elB) return -1;
}
return b.length - a.length;
};
console.log(compareArrays([-2], [-1])) # -1
console.log(compareArrays([], [])) # 0
console.log(compareArrays([null], [undefined])) # 0
console.log(compareArrays([1, 2, 3], [1, 2, 3, 4])) # 1
console.log(compareArrays([0, 2], [0, 1])) # 1
console.log(compareArrays([1], [NaN])) # 0
console.log(compareArrays([NaN], [1])) # 0

Related

What does >>>= mean? [duplicate]

This question already has answers here:
JavaScript triple greater than
(4 answers)
Closed 2 years ago.
While I was checking the lodash code, I came up with a question I was curious about.
// slice.js
function slice(array, start, end) {
let length = array == null ? 0 : array.length
if (!length) {
return []
}
start = start == null ? 0 : start
end = end === undefined ? length : end
if (start < 0) {
start = -start > length ? 0 : (length + start)
}
end = end > length ? length : end
if (end < 0) {
end += length
}
length = start > end ? 0 : ((end - start) >>> 0)
start >>>= 0
let index = -1
const result = new Array(length)
while (++index < length) {
result[index] = array[index + start]
}
return result
}
export default slice
Specifically, I am curious about why this code exists in this part.
((end - start) >>> 0)
As far as I know, the bit operator shifts the position of a binary number, but I am curious why it shifts 0 times.
>>>=
And >>>= This operator is the first time I saw it.
Does anyone know what it means?
>>> is called unsigned right shift (or zero fill right shift). You may have known of left/right shift.
Basically it shifts the specified number of bits to the right. You can find it here
So >>>= is basically the right shift assignment.
a >>>= b
is equivalent to:
a = a >>> b
The unsigned right shift operator (a >>> b) does shift the bits of the variable a by b bits as you said.
It always returns a positive integer, so a >>> 0 would be used to make sure that the input isn't say, negative, or a string, or otherwise not a positive integer.
a >>>= b is similar to a += b, that is, it applies the right shift b to a and then assigns the output to a, similar to how a += b adds b to a and then assigns the result to a. So a >>>= b is equivalent to a = a >>> b like a += b is equivalent to a = a + b.

Are multiple comparison operators possible in javascript? [duplicate]

This question already has answers here:
Dual or triple (or even multiple) comparison in JavaScript
(3 answers)
Closed 2 years ago.
So i was writing in the Browser console
4 < 5
true
4 < 5 < 10
true
7 < 4 < 10
true
The first two statements look ok, why is the last statement also correct? I would have thought (as in mathematics) the expression would be 'AND'ed ? can any one point me to MDN or similar resource which talks about this and the rules ?
What Javascript does, is evaluate the left side first:
4 < 5 => true
It then continues on the rest:
true < 10 => true
because true on the left side is coerced to a number (1), and 1 < 10 === true. (false in comparisons with numbers is coerced to 0).
Check these funny-looking "goofs":
console.log(3 < 2 < 1)
console.log(1 < 1 < 1)
Beside the not working approach to write a continuing check with more than one copmparison operator, and while the next comparison takes place the the result of the previous comparison, you could take an array and a function for the comparison operator and iterate the items for every pair to check. Then return the result.
const compare = (values, fn) => values.slice(1).every((b, i) => fn(values[i], b));
console.log(compare([7, 4, 10], (a, b) => a < b)); // false
console.log(compare([4, 7, 10], (a, b) => a < b)); // true
console.log(compare([2, 1, 0], (a, b) => a > b)); // true
console.log( false < 10) // true
console.log( true < 10) // true
because false (0) is less than to 10
and true (1) is also less than to 10.
4 < 5 evaluates to true. Then true is compared with 10. Javascript converts true to 1 and as 1 is smaller than 10 the result is true.
With this logic if you try 4 < 5 < 3 this will also return true with the same logic, and 4 < 5 < 1 will return false.

Why does the statement `0 < 0.5 < 1` reduce to false?

I recently discovered the ECMAScript Spec, which I was able to use to answer a question I've had about Math.random() for a while; namely whether or not it would ever generate 0 without the help of Math.floor().
The ECMAScript Spec specifies that 0 <= Math.random() < 1, unlike literally anyone else for some reason. I hopped over to the console and ran a test before saving it in my notes but noticed that statement reduces to false.
Below is a function that tests everything about comparison statements that I thought might be causing this lie. I call the function twice to generate two arrays of Boolean values, and the results seem to imply that literally this statement: 0 <= Math.random() < 1 - and this statement alone, returns FALSE where it should return TRUE. Especially when you consider bonus round where I test the exact same statement but with an additional comparison tacked onto the end, and it also returns true
function getTruths( a, b, c ) {
return [
a + 1 < b + 1,
a + 1 < c + 1,
b + 1 < c + 1,
a + 1 < b + 1 < c + 1,
a + 0 < b + 0,
a + 0 < c + 0,
b + 0 < c + 0,
a + 0 < b + 0 < c + 0
];
}
function demonstrate() {
// array of truth
console.log( getTruths( 0, 1, 2 ) );
// array of lies
console.log( getTruths( 0, 0.5, 1 ) );
// bonus round
return [ 0 < 0.5 < 1 < 1.5 ];
}
demonstrate();
So I did some more plucking around and learned that it isn't just that. it seems that a and b can actually be any value lower that one and equal to or greater than zero, just as long as b is still bigger than a, and c is still equal to 1 of course... and given those parameters, no matter what, the return is still FALSE. If you add 1 to everything though suddenly you're in good shape again, just as in the function provided above.
Anyway can someone explain this to me? Thanks.
a < b < c
is interpreted as
(a < b) < c
The result value from a relational operator like < is a boolean, either true or false. If c is a number, then, that boolean will be converted to a number, either 1 (true) or 0 (false). Thus c is compared to either 0 or 1, not the values of either a or b.
The proper way to write "is b strictly between a and c" is
a < b && b < c

How "Math.random() * arr.length | 0" works for return a random index for an array

I've been working in a legacy code that have a certain functionality that should return a random item for array and I see the following expression:
array[Math.random() * arr.length | 0]
My first impression was try to undestand the | operator but i can't figure out how does work.
I test the expression in the chrome console and I see that always returns a valid index with this:
let array = [1,2,3,4]
for(let i = 0; i < 5000; i++){
console.log(array[Math.random() * arr.length | 0]);
}
How "Math.random() * arr.length | 0" works for return a random index for an array?
Math.random() returns a number >= 0 and < 1.
* arr.length returns a number >= 0 and < arr.length, yet this can't be used as an index, because it would have a fractional part
| 0 coerces the left expression to a integral number then applies the bitwise or with the number zero, which is always the other number
This said, what makes this work is the implicit conversion (called coersion) in the operator |.
In this context, | 0 is being used to round down to the nearest integer. So Math.random generates a number in the range 0 <= number < 1, then this gets multiplied by arr.length giving a number between 0 <= number < arr.length, which is then rounded down giving an integer between 0 and arr.length -1, inclusive
let array = [1, 2, 3, 4]
function randomIndex() {
let random = Math.floor(Math.random () * array.length)
return array [random]
}
console.log(randomIndex())

What is the best way to determine if a given number is a power of two?

Is there a more effective way to return true if n is a power of two or false if not?
function isPowerOfTwo(n) {
return Math.pow(2, Math.round(Math.log(n) / Math.log(2)));
}
You can actually use ECMAScript5 Math.log:
function powerOfTwo(x) {
return (Math.log(x)/Math.log(2)) % 1 === 0;
}
Remember, in math, to get a logarithm with an arbitrary base, you can just divide log10 of the operand (x in this case) by log10 of the base. And then to see if the number is a regular integer (and not a floating point), just check if the remainder is 0 by using the modulus % operator.
In ECMAScript6 you can do something like this:
function powerOfTwo(x) {
return Math.log2(x) % 1 === 0;
}
See the MDN docs for Math.log2.
Source: Bit twiddling Hacks,
function powerOf2(v) {
return v && !(v & (v - 1));
}
You just bitwise AND the previous number with the current number. If the result is falsy, then it is a power of 2.
The explanation is in this answer.
Note:
This will not be 100% true for programming, mathematical, [also read 'interviewing']. Some edge cases not handled by this are decimals (0.1, 0.2, 0.8…) or zero values (0, 0.0, …)
Using bitwise operators, this is by far the best way in terms of efficiency and cleanliness of your code:
function PowerofTwo(n){
return ((x != 0) && !(x & (x - 1)));
}
what it does is checks the bits that make up the number, i.e. 8 looks like this:
1 0 0 0
x-1 or 7 in this case looks like this
0 1 1 1
when the bitwise operator & is used it invokes an && on each bit of the number (thus 1 & 1 = 1, 1 & 0 = 0, 0 & 1 = 0, 0 & 0 = 1):
1 0 0 0
-0 1 1 1
=========
0 0 0 0
since the number turns into an exact 0 (or false when evaluted as a boolean) using the ! flag will return the correct answer
if you were to do this with a number like 7 it would look like this:
0 1 1 1
-0 1 1 0
=========
1 1 1 0
returning a number greater than zero causing the ! flag to take over and give the correct answer.
A number is a power of 2 if and only if log base 2 of that number is whole. The function below computes whether or not that is true:
function powerOfTwo(n){
// Compute log base 2 of n using a quotient of natural logs
var log_n = Math.log(n)/Math.log(2);
// Round off any decimal component
var log_n_floor = Math.floor(log_n);
// The function returns true if and only if log_n is a whole number
return log_n - log_n_floor == 0;
}
Making use of ES6's Math.clz32(n) to count leading zeros of a 32-bit integer from 1 to 2³² - 1:
function isPowerOf2(n) {
return Math.clz32(n) < Math.clz32(n - 1);
}
/**
* #param {number} n
* #return {boolean}
*/
const isPowerOfTwo = function(n) {
if(n == 0) return false;
while(n % 2 == 0){
n = n/2
}
return n === 1
};
function PowerOfTwo(n){
// Exercise for reader: confirm that n is an integer
return (n !== 0) && (n & (n - 1)) === 0;
}
console.log(PowerOfTwo(3))
console.log(PowerOfTwo(4))
This is for a specific online course that requires an answer in a specific way.
Without using libraries and other methods just loops and .push.
you need to create an inner loop using while
it should start with 1
keep multiplying it with 2 until i,j,k or whatever is greater than the current number(array) so it will have to do 2 4 6 8 10 12 14 16 18 until it is greater than the number
then it will go to the outer loop then repeat again until
const numbers = [5, 3, 9, 30];
const smallestPowerOfTwo = arr => {
let results = new Array;
// The 'outer' for loop -
for (let i = 0; i < arr.length; i++) {
number = arr[i];
// The 'inner' while loop
j = 1;
while (j < number) { //starting from 1 then multiplied by 2 then by 2 again untill it is more than the number
j = j * 2;
}
results.push(j);
}
return results
}
console.log(smallestPowerOfTwo(numbers))

Categories

Resources