Why is ~null === -1? - javascript

A questions that stumped me on this JavaScript test was that ~null evaluates to -1.
Why does ~null evaluate to -1?

That's because ~ is a numeric operator, so it casts null to 0 first:
> ~0
-1
It would be equivalent to this expression:
~(+null)
Likewise:
> ~[]
-1
> ~{}
-1

First of all, ~ is a bitwise NOT operator. That means it flips all the bits in the number representation. 0010 1010 becomes 1101 0101.
As a consequence of computers using 2's complement for storing numbers, this equality holds:
~number == -number - 1
As can be shown from my previous example:
0010 1010 (this represents number 42)
1101 0101 (this represents number -43)
Now, because ~ is an operator that operates on numbers, its argument gets cast to a number first. Since null gets cast to a 0, you get -1 as a result (according the above equation).

Related

Difference Between Single And Double Vertical Bar (|, ||) in JavaScript? [duplicate]

This question already has answers here:
What's the difference between ( | ) and ( || )?
(7 answers)
Closed 4 years ago.
For a while, I have used "||" as the "or" indicator. One day, I was debugging some things in a console, and I accidentally put a single | instead of two. It still worked as expected.
console.log(0||1); // 1
console.log(0|1); // 1
Is there any difference? Here, there evidently isn't, but there might be some hidden difference that I don't know about. I apologize if this is a duplicate, but I assure you I have looked for the answer beforehand.
That is called a bitwise OR, meaning it ORs the individual bits that compose a value based on binary rules.
a b a OR b
0 0 0
0 1 1
1 0 1
1 1 1
For your example, 0 in binary is just 0000, and 1 in binary is 0001.
Thus 0|1 is:
0000 | 0001
Which, when we apply the table above between each binary digit of the two numbers:
0 or 0 = 0
0 or 0 = 0
0 or 0 = 0
0 or 1 = 1
give us 0001, which when converted to decimal becomes 1.
The way || (logical OR) behaves is using coercion rules which returns the first truthy item (or just the last item) in a sequence of ||.
Since 0 is falsy, 0 || 1, will return 1.
Just because the answers happen to be the same in these two situations, does not mean that the operations always produce equal results.
For instance:
2|3 === 3
2||3 === 2
| is a bitwise OR.
Performs the OR operation on each pair of bits. a OR b yields 1 if either a or b is 1
|| is a logical OR.
In your example, 0|1 will evaluate to 1, because ... 0000 | ... 0001 evaluates to ... 0001.
0||1 will evaluate to 1 because 0 is falsy so it'll return the right operand 1

Confusion with left-shift operator

I am trying to create a 32-bit bitmask in JS. However, I don't understand what's happening here:
$ node
> const num = Math.pow(2, 31) - 1
undefined
> num
2147483647
# So far, so good
> num.toString(2)
'1111111111111111111111111111111'
> num.toString(2).length
31
# According to MDN, the left-shift operator does:
# "Excess bits shifted off to the left are discarded.
# Zero bits are shifted in from the right."
# But that's not what we see here. Instead, it seems to be wrapping.
> num << 1
-2
> (num << 1).toString(2)
'-10'
According to my understanding of the MDN docs, I'd expect to have a bitmask of 31 1s followed by 1 0. Instead, I get -10. What's going on here?
Javascript doesn't have Integer, but bitwise operators only make sense on Integer.
So before bitwise operators, javascript will apply ToInt32(val) to your num.
For "Signed 32 bits Integer", the top bit represents 'signed'.
Finally your num overflow the 'signed bit'.
My English is poor, you can check ECMAScript's Language Specification.
It is not wrapping. It is exactly working as the documentation you've linked. In your linked documentation, it says:
The operands of all bitwise operators are converted to signed 32-bit integers in two's complement format.
Your num is 2147483647, and this number in two's complement format is:
01111111 11111111 11111111 11111111
After left shifting num by 1, it becomes:
11111111 11111111 11111111 11111110
The above 32-bit two's complement value is -2 in decimal number. Hence, you get:
> num
2147483647
> num << 1
-2
If you call toString(2) with a negative decimal number -2, it follows some special rule of toString(). What it does is:
Take the magitude of the decimal. (-2 => 2)
Convert the decimal to base-2 string representation. (2 => '10')
Put the minus sign in front. ('10' => '-10')
Therefore, you get:
> (num << 1).toString(2)
> -10
You also get:
> (-2).toString(2)
> -10
Today I check your question again then know I misunderstand your main point yesterday.
This is your main point:
" I'd expect to have a bitmask of 31 1s followed by 1 0. Instead, I get -10."
Because Two's complement.
A negative number doesn't express value directly.
let num=Math.pow(2,31)-1
//num in memory=> 0111111111111111111111111111111
// ^
// |
// signed bit
//This number is positive, so
//nothing to do=> 0111111111111111111111111111111
num = num<<1
//num in memory=> 1111111111111111111111111111110
// ^
// |
// signed bit
//This number is negative, so flip then add 1
//flip => 1000000000000000000000000000001
//add 1 => 1000000000000000000000000000010 => '-10'

What does the combination of !!~ do? [duplicate]

If you read the comments at the jQuery inArray page here, there's an interesting declaration:
!!~jQuery.inArray(elm, arr)
Now, I believe a double-exclamation point will convert the result to type boolean, with the value of true. What I don't understand is what is the use of the tilde (~) operator in all of this?
var arr = ["one", "two", "three"];
if (jQuery.inArray("one", arr) > -1) { alert("Found"); }
Refactoring the if statement:
if (!!~jQuery.inArray("one", arr)) { alert("Found"); }
Breakdown:
jQuery.inArray("one", arr) // 0
~jQuery.inArray("one", arr) // -1 (why?)
!~jQuery.inArray("one", arr) // false
!!~jQuery.inArray("one", arr) // true
I also noticed that if I put the tilde in front, the result is -2.
~!!~jQuery.inArray("one", arr) // -2
I don't understand the purpose of the tilde here. Can someone please explain it or point me towards a resource?
There's a specfic reason you'll sometimes see ~ applied in front of $.inArray.
Basically,
~$.inArray("foo", bar)
is a shorter way to do
$.inArray("foo", bar) !== -1
$.inArray returns the index of the item in the array if the first argument is found, and it returns -1 if its not found. This means that if you're looking for a boolean of "is this value in the array?", you can't do a boolean comparison, since -1 is a truthy value, and when $.inArray returns 0 (a falsy value), it means its actually found in the first element of the array.
Applying the ~ bitwise operator causes -1 to become 0, and causes 0 to become `-1. Thus, not finding the value in the array and applying the bitwise NOT results in a falsy value (0), and all other values will return non-0 numbers, and will represent a truthy result.
if (~$.inArray("foo", ["foo",2,3])) {
// Will run
}
And it'll work as intended.
!!~expr evaluates to false when expr is -1 otherwise true.
It is same as expr != -1, only broken*
It works because JavaScript bitwise operations convert the operands to 32-bit signed integers in two's complement format. Thus !!~-1 is evaluated as follows:
-1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two's complement representation of -1
~-1 = 0000 0000 0000 0000 0000 0000 0000 0000b // ~ is bitwise not (invert all bits)
!0 = true // ! is logical not (true for falsy)
!true = false // duh
A value other than -1 will have at least one bit set to zero; inverting it will create a truthy value; applying ! operator twice to a truthy value returns boolean true.
When used with .indexOf() and we only want to check if result is -1 or not:
!!~"abc".indexOf("d") // indexOf() returns -1, the expression evaluates to false
!!~"abc".indexOf("a") // indexOf() returns 0, the expression evaluates to true
!!~"abc".indexOf("b") // indexOf() returns 1, the expression evaluates to true
* !!~8589934591 evaluates to false so this abomination cannot be reliably used to test for -1.
The tilde operator isn't actually part of jQuery at all - it's a bitwise NOT operator in JavaScript itself.
See The Great Mystery of the Tilde(~).
You are getting strange numbers in your experiments because you are performing a bitwise logical operation on an integer (which, for all I know, may be stored as two's complement or something like that...)
Two's complement explains how to represent a number in binary. I think I was right.
~foo.indexOf(bar) is a common shorthand to represent foo.contains(bar) because the contains function doesn't exist.
Typically the cast to boolean is unnecessary due to JavaScript's concept of "falsy" values. In this case it's used to force the output of the function to be true or false.
jQuery.inArray() returns -1 for "not found", whose complement (~) is 0. Thus, ~jQuery.inArray() returns a falsy value (0) for "not found", and a truthy value (a negative integer) for "found". !! will then formalise the falsy/truthy into real boolean false/true. So, !!~jQuery.inArray() will give true for "found" and false for "not found".
The ~ for all 4 bytes int is equal to this formula -(N+1)
SO
~0 = -(0+1) // -1
~35 = -(35+1) // -36
~-35 = -(-35+1) //34
Tilde is bitwise NOT - it inverts each bit of the value. As a general rule of thumb, if you use ~ on a number, its sign will be inverted, then 1 will be subtracted.
Thus, when you do ~0, you get -1 (0 inverted is -0, subtract 1 is -1).
It's essentially an elaborate, super-micro-optimised way of getting a value that's always Boolean.
The ~ operator is the bitwise complement operator. The integer result from inArray() is either -1, when the element is not found, or some non-negative integer. The bitwise complement of -1 (represented in binary as all 1 bits) is zero. The bitwise-complement of any non-negative integer is always non-zero.
Thus, !!~i will be true when integer "i" is a non-negative integer, and false when "i" is exactly -1.
Note that ~ always coerces its operand to integer; that is, it forces non-integer floating point values to integer, as well as non-numeric values.
You're right: This code will return false when the indexOf call returns -1; otherwise true.
As you say, it would be much more sensible to use something like
return this.modifiedPaths.indexOf(path) !== -1;
The ~ operator is the bitwise NOT operator. What this means is that it takes a number in binary form and turns all zeroes into ones and ones into zeroes.
For instance, the number 0 in binary is 0000000, while -1 is 11111111. Likewise, 1 is 00000001 in binary, while -2 is 11111110.
My guess is that it is there because it's a few characters shorter (which library authors are always after). It also uses operations that only take a few machine cycles when compiled into the native code (as opposed to the comparison to a number.)
I agree with another answer that it's an overkill but perhaps might make sense in a tight loop (requires performance gain estimation, though, otherwise may turn out to be premature optimization.)
I assume, since it is a bitwise operation, it is the fastest (computationally cheap) way to check whether path appears in modifiedPaths.
As (~(-1)) === 0, so:
!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false

Meaning of ~ in javascript function

I'm reading this javascript function:
if (~['bacon', 'burger'].indexOf(type)) {
this.res.writeHead(200, { 'Content-Type': 'text/plain' });
this.res.end('Serving ' + type + ' sandwich!\n');
}
But I'm not sure what means ~ some one know when I use it or what meaning?
~ is the bitwise NOT operator. It toggles every bit of a number.
0 becomes -1.
-1 becomes 0.
No other numbers become zero.
That means that
if (~['bacon', 'burger'].indexOf(type)) {
is a confusing way of writing
if (['bacon', 'burger'].indexOf(type) == -1) {
indexOf returns -1 when it doesn't find the string.
~ is a Bitwise NOT operator...
Read more
In this instance, the ~ allows that code to turn the return value of .indexOf() — which is a number indicating the position of the searched-for value in the array — into a boolean. In other words, it takes the "where is the value" result and turns it into a "is the value in the list" result.
How? Well, .indexOf() returns -1 when the value is not found, and a number greater than or equal to zero if it is. The ~ operator converts its numeric argument to a 32-bit integer and then inverts every bit. That process happens to turn -1 to 0, and any positive integer to some negative non-zero value, and 0 to -1. When such results are subsequently examined as boolean values, the original -1 will be false (because 0 is "falsy") while the integers greater than or equal to zero will be true (because they're all converted to some non-zero value).
Bitwise NOT (~ a) Inverts the bits of its operand.
EXAMPLE
9 (base 10) = 00000000000000000000000000001001 (base 2)
--------------------------------
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base
10)
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

In javascript what is the difference between operator '~' and '!'

I am out of theories, i don't know what else to say.
So far i always thought that both changed the value to false.
But, !, changes to true/false.
While, ~ , changes to negative number with 1 less so 2 become -3. Why and how.
~ (Bitwise NOT)
Performs the NOT operator on each bit. NOT a yields the inverted value (a.k.a. one’s complement) of a. The truth table for the NOT operation is:
a NOT a
0 1
1 0
Example
9 = 00000000000000000000000000001001 (base 2)
--------------------------------
~9 = 11111111111111111111111111110110 (base 2) = -10 (base 10)
Answer sourced from The tilde ~ operator in JavaScript.
! is a logical operator, its result is either true or false, while ~ is a bitwise operator.
If you don't understand why ~number is -number - 1 have a look at two's complement.
I am out of theories, i don't know what else to say.
In this case have a look at the language's documentation.
! is a boolean operator, it negates the result of a boolean expression.
~ on the other side is the bitwise not operator, which basically means, it flips all the bits in your operand, say, -1 which is represented by all 1 bits to 0 (which means 0 bits are set).

Categories

Resources