Difference between (|) Bitwise OR vs (^) Bitwise XOR in JavaScript - javascript

I'm really getting confused on the use of the | OR vs ^ XOR in JavaScript, illustrated in the simple example below;
(function sayHi(n){
if(n < 1) //base case
return;
console.log("Hi!!" | "Hello!!") ;
sayHi(n - 1); //recurse
})(5);
(function sayHi(n){
if(n < 1) //base case
return;
console.log("Hi!!" ^ "Hello!!") ;
sayHi(n - 1); //recurse
})(5);
(function sayHi(n){
if(n < 1) //base case
return;
console.log(2 | 6) ;
sayHi(n - 1); //recurse
})(5);
(function sayHi(n){
if(n < 1) //base case
return;
console.log(2 ^ 6) ;
sayHi(n - 1); //recurse
})(5);
I'm confused about when, how, why, where I should appropriate use | vs ^.
Can someone please help me make sense the major difference between OR and XOR operations?
I was reading the documentation for JavaScript from MDN web Docs to better understand the concept of bitwise operations, but I am struggling to understand their significant difference.
I just want to make sure I continue to use these operations correctly henceforth.
Thanks a lot for the anticipated help!

OR and XOR are different operators:
OR:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
XOR
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
If you have two bits and combine these with OR, the result will be 1, if one of these bits or both are 1. If you combine them with XOR (Exclusive OR) then it will be 1 if only one of these bits are 1 (not if both).

| is a bitwise or
So, if either bit is set in two operands, it will be set in the result
^ is an exclusive or, so if one bit is set in one of the operands, it will be set in the result, otherwise, it will not be set.
var x,y;
for (x = 0; x <= 1; x++) {
for (y = 0; y <= 1; y++) {
console.log('XOR '+ x + "^" + y + "=" + (x^y));
console.log('OR '+ x + "|" + y + "=" + (x|y));
}
}

Bitwise operators are typically used for checking whether a bit is set in a binary or not. You can vision it as a set of boolean values been compact it as a string 11100101, where each bit is used to represent the boolean flag true or false, 1 for set and 0 for unset respectively.
Binary reading is done abit different from our usual English. It is done from right to left, with the most left bit been the most significant bit because it holds the greatest value and the left hand side bit been the least.
Example:
Value: 64 = binary 10000000
Value: 1 = binary 00000001
Now back to your question.
Q: I'm confused about when, how, why, where I should appropriate use | vs ^.
A:
Bitmask and its operators are more commonly seen in low level programming where memory is a constraint (small computing device) or on performance critical application.
Sounds advantageous to use right? But they have their downside as well and it is code readability. Memory is cheap and processing power is much more greater than what it used to be, so people tend to forgo this bit of advantage when doing high level application programming.
Q: Can someone please help me make sense the major difference between OR and XOR operations?
OR and XOR operations are used for comparing two binaries. Let say binary A and binary B.
In layman term. The OR operations | can be read as if the bit in A OR B is set then return as set, which is 1.
Example:
10000000 // Value 64 in binary
00000001 // Value 1 in binary
10000001 // Gives you 65 when you perform | OR operation
= 65
XOR operation works a bit like OR but it has another special ability that is when two bits are the same it returns you 0 instead.
Example:
10000001 // Value 65 in binary
10000000 // Value 64 in binary
00000001 // Gives you 1 when you perform ^ XOR operation
= 1
From memory, you generally only use the AND & operator to check whether a bit is set or not. So you might be more interested in it and also the shift operations.

Your code doesn't make sense, bitwise operators (OR, XOR, AND) can only be used on numbers, not strings.
Each number is represent in memory by bits, each of which is 1 or 0 (true or false, on or off, etc). 1 and 0 are digits, just like 1, 2, 3, 4 are digits in our counting system. This counting system used by computers is called binary.
Bitwise operations basically perform the namesake operation (OR, XOR, or AND) on every single bit in the two operands.
Take 5 ^ 3 (5 XOR 3) for example:
5 is represented in binary as 00000101
3 is represented in binary as 00000011
For each operation, you have a left input, and a right input.
XOR stands for eXclusive OR, and returns 1 if the left OR the right input is 1, but not if they are both 1.
OR returns 1 if either of the inputs is 1, so if both are 1, then the output will also be 1.
A bitwise operation on a number performs this for every corresponding bit in each number, so 5 ^ 3 = 00000110, which is 6.
Note: Binary numbers are written from right to left. Each digit corresponds to a power of 2, like how digits correspond to powers of 10 when counting. The leftmost digit represents the highest power of 2 (in this case, 2 to the 7th, which is 128).
0 ^ 0 = 0 for the first 5 bits
1 ^ 0 = 1 for the 6th bit
0 ^ 1 = 1 for the 7th bit
1 ^ 1 = 0 for the 8th bit
Meanwhile, 5 | 3 = 00000111, which is 7.
0 | 0 = 0 for the first 5 bits
1 | 0 = 1 for the 6th bit
0 | 1 = 1 for the 7th bit
1 | 1 = 1 for the 8th bit

They are different math (logical) operators, more related to math than JavaScript.
OR / |, or called "Inclusive OR", is similar to the English phrase "A and/or B", there are 3 possibilities: not A but B, not B but A, both A and B.
XOR / ^, or called "Exclusive OR", is similar to the English phrase "either A or B", there are only 2 possibilities: not A but B, not B but A. You can see that "both A and B" is excluded, so called "exclusive".
Reference:
https://en.wikipedia.org/wiki/Logical_connective

Related

In JavaScript, can bit shifting be used to isolate 1 or more bits in a byte?

In JavaScript code where the 8 bits of a byte represent 8 Boolean "decisions" (aka: flags), there is a need to isolate each given bit for conversion to a Boolean variable. Consider my solution using String parsing:
var bitParser = function (_nTestByte, _nBitOrdinal) {
var bits = ("00000000" + _nTestByte.toString(2)).slice(-8); // convert to binary and zero-pad
return bits[_nBitOrdinal] === "1";
};
console.log(bitParser(0b10100101, 2)); // ECMAScript 6+ prefix, returns true
It works, and shows the desired result. However I have a hypothesis stating that a bit shifting technique would be a faster option than String manipulation. I tend to believe that but desire to prove it.
The problem is, I have yet to produce such a function that works correctly, let alone something I can test. I have created the following logic plan that I believe is accurate:
/*
LOGIC PLAN
----------
0) Remember: all bitwise operators return 32 bits even though we are using 8
1) Left shift until the desired bit is the left-most (highest) position;
2) Right shift (zero filling) 31 bits to eliminate all right bits
*/
The implementation of the login plan follows. Because of the 32 bit nature of bitwise operators, its my belief that the entire left 3 bytes (24 bits) must be shifted off first before we even reach the byte being worked on. Then, assuming a scenario where the 3rd bit from the left (String ordinal 2) is the desired bit, I am shifting off 2 more bits (ordinals 0 & 1), for a total of 26 bits of left shifting.
This should produce a binary number with the desired bit all the way left followed by 31 undesired zero bytes. Right shifting those 31 bits away produces a binary with 31 (now) leading zero bits which evaluates to whatever the value of the desired bit is. But of course, I would not be writing this question if THAT were true, now would I? :-)
// hardcoded, assuming the second "1" (ordinal 2) is the bit to be examined
console.log((0b10100101 << 26) >> 31); // instead of 1, returns -1
I feel like I am really close, but missing something or pushing JavaScript too hard (lol).
In JavaScript code where the 8 bits of a byte represent 8 Boolean "decisions" (aka: flags), there is a need to isolate each given bit for conversion to a Boolean variable...
If that's the actual goal, bitshifting is neither necessary nor useful: Just use a bitwise & with the desired bit, which will give you either 0 or a number with that bit set. 0 is falsy, the number with a bit set is truthy. You can either use that as-is, or force it to boolean via !!flag or Boolean(flag):
Here's your bitParser function using bitmasking:
var bitParser = function (_nTestByte, _nBitOrdinal) {
return !!(_nTestByte & Math.pow(2, _nBitOrdinal));
};
console.log(bitParser(0b10100101, 2)); // true
console.log(bitParser(0b10100101, 1)); // false
Rather than doing the Math.pow every time, of course, we'd probably be better off with a lookup table:
var bits = [
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00100000,
0b01000000,
0b10000000
];
var bitParser = function (_nTestByte, _nBitOrdinal) {
return !!(_nTestByte & bits[_nBitOrdinal]);
};
console.log(bitParser(0b10100101, 2)); // true
console.log(bitParser(0b10100101, 1)); // false
From your question I took
console.log((0b10100101 << 26) >> 31); //instead of 1, returns -1.
And to answer your question why it returned -1 instead of 1
You need to do unsigned right shift >>> instead of signed one >>
console.log((0b10100101 << 26 ) >>>31);
Yes it can, and what you're doing is almost correct.
Integers are represented as a 32bit binary number, with the leftmost bit representing the sign (it's 1 if the number is negative and 0 if the number is positive). Lets look at some of the numbers' representations:
//last 31 digits keeps increasing as the number decreases
// ...
-2 => 0b11111111111111111111111111111110
-1 => 0b11111111111111111111111111111111
0 => 0b00000000000000000000000000000000
1 => 0b00000000000000000000000000000001
2 => 0b00000000000000000000000000000010
// ...
// last 31 digits keep increasing as the number increases
Now, what you're having (0b10100101 << 26) should give you 10010100000000000000000000000000, which you'd expect to be a big negative number (because the left-most bit is 1). Then right afterwards, you have >> 31 which you're expecting to strip off all 31 bits and leave you with the left-most bit.
That should work, but it's not what's happening. And why is that? It's because the people who came up with ECMAScript thought it would make more sense if 4 >> 1 returns 2 and -4 >> 1 returns -2.
4 >> 1 // returns 2 which is 0b00000000000000000000000000000010
0b0000000000000000000000000000000100 >> 1 // returns 2, same
-4 >> 1 // returns -2, which is 0b11111111111111111111111111111110
But -4 is 0b11111111111111111111111111111100, and for your purposes right shifting it by 1 should yield 0b01111111111111111111111111111110 (big positive number, since left-post bit is 0), and that's not -2!
To overcome that, you can use the other right shift operator which doesn't care about about the sign: >>>. -4 >>> 1 is 2147483646 which is what we want.
So console.log((0b10100101 << 26) >>> 31); gives you 1, which is what you want. You can also keep using >> and regarding any negative outcome to be a result of 1 being the chosen bit.
The most simple way to achieve your actual need is to use simple conditions rather than trying to isolate bits.
var bitParser = function (_nTestByte, _nBitOrdinal) {
return (_nTestByte & _nBitOrdinal);
};
console.log(bitParser(6, 2) ? true : false); // true
console.log(bitParser(6, 1) ? true : false); // false
I adapted the console.log() expression in a way that may seem complicated.
It's only to really show the logical result at this step, while I didn't choose to use !! inside of the function, so returning a truly/falsy value rather than true|false.
Actually this way keeps all the most simple possible, because the expected use else where in the code is if (bitParser(...)), which automatically casts the result to boolean.
BTW, this works whatever is the _nTestByte size (may be more than 1 byte).

Can someone please explain to me what the "|" symbol is doing in Javascript?

What does it do?
At first I thought it was a shorthand way of doing Math.max()
Every time I did (1 | 0) or (0 | 2985235), I got back the larger number.
However, I was wrong, as I soon found out when I posted this question with the example:
(128|256|0) which does not evaluate to 256.
Thanks for the helpful replies.
| is a bitwise OR operator.
To see what it does, consider the binary form of the numbers:
128 = 010000000
256 = 100000000
0 = 000000000
The result is from performing OR bit-by-bit
384 = 110000000
I guess you might encounter this pattern in the logic to represent options.
For example,
128 = option 1
256 = option 2
384 = both option 1 & 2
| is a bitwise operator in Javascript. So before evaluating those integers, first convert them to binary.
0 -> 000000000
128 -> 010000000
256 -> 100000000
There might be more preceding zeros depending on your data types. Anyway | as a bitwise OR operator, will evaluate each bit from those two integers.
So you will get 110000000 as an result, which is 384 in decimal.
P.S. OR operation: if any one of those hold true, then true.

Left shifting with a negative shift count in Javascript

A thing which I noticed in Javascript -
a << -1
Returns 0 when a = even.
Returns -2147483648 when a = odd.
Similarly, different values are returned when -1 is changed to some other -ve number.
Can someone explain what bit operations are taking place under the hood ? Or is the behavior undefined ?
Thanks
EDIT
Also shouldn't Zero-fill right shift i.e. -2 >>> 1 return 7 ?
-2 = 1110. After, right shift with zero-fill, it should give 0111 = 7
but
a = -2; console.log(a >>> 1);
returns
2147483647
I too wondered about this which is how I landed here. I’ve done a little research and figured out the behavior. Essentially JavaScript treats the operand and shift value as sequences of bits rather than as numbers. It works with 32 bit integers (floats get truncated) and the maximum shift is 32 bits. If we shift by a number greater than 32, all the bits would shift out, resulting in zero. To ensure the shift is less than or equal to 32, JavaScript truncates the 5 least significant bits [a << (b&0x1F)] or possibly with the modulus method [a << (b%32)] which yields the same result.
With that out of the way, think of the negative number you are shifting by as a sequence of bits, not a negative number (i.e. -1). In this case b = -1 = 0xFFFFFFFF. Since this number is larger than 32, it is truncated 0xFFFFFFFF & 0x1F = 31 or 0xFFFFFFFF % 32 = 31.
So in your example “a" gets shifted all the way from the least significant bit to the most significant bit (the sign bit). Therefor the result of the shift is either 0x00000000 or (0x80000000 = -2147483648) depending on whether the operand had the 1 bit set (odd or even).
Got the answer to the second part of my question i.e. -2 >>> 1 = 7.
Javascript always deals with 32 bits. So when I do -2 >>> 1, what really happens under the hood is -
11111111111111111111111111111110 >>> 1 which gives 01111111111111111111111111111111 = (2147483647)base10
The LeftShift operator adds zeros to the right of the binary representation of a number, shifting the bits to the left. Only the 5 least significant digits of the additive expression are used. So:
var x = 5 // 101
alert( x << 1 ); // 1010 = 10
alert( x << 2 ); // 10100 = 20
alert( x << 3 ); // 101000 = 40
alert( x << 4 ); // 1010000 = 80
alert( x << 64 ); // 101 = 5
The last expression returns 5 as shift only uses the last 5 bits of the the additive expression, which is 1000000 so only the 00000 part is used.

what does the symbol >> means in javascript

What does the >> symbol mean? On this page, there's a line that looks like this:
var i = 0, l = this.length >> 0, curr;
It's bitwise shifting.
Let's take the number 7, which in binary is 0b00000111
7 << 1 shifts it one bit to the left, giving you 0b00001110, which is 14
Similarly, you can shift to the right: 7 >> 1 will cut off the last bit, giving you 0b00000011 which is 3.
[Edit]
In JavaScript, numbers are stored as floats. However, when shifting you need integer values, so using bit shifting on JavaScript values will convert it from float to integer.
In JavaScript, shifting by 0 bits will round the number down* (integer rounding) (Better phrased: it will convert the value to integer)
> a = 7.5;
7.5
> a >> 0
7
*: Unless the number is negative.
Sidenote: since JavaScript's integers are 32-bit, avoid using bitwise shifts unless you're absolutely sure that you're not going to use large numbers.
[Edit 2]
this.length >> 0 will also make a copy of the number, instead of taking a reference to it. Although I have no idea why anyone would want that.
Just like in many other languages >> operator (among << and >>>) is a bitwise shift.

Next odd number in javascript

To find the next odd number for an input the following code is being used:
a=5.4; // Input
b=Math.ceil(a); // Required to turn input to whole number
b=b+(((b % 2)-1)*-1); // Gives 7
The ceil rounding function is required.
Is this safe and is there a more compact way to do this?
EDIT: When the input is already an odd whole number then nothing happens. For example 5.0 will return 5
How about just
b += b % 2 ^ 1;
The remainder after dividing by 2 will always be 0 or 1, so the ^ operator (exclusive-OR) flips it to the opposite.
(Also, (b & 1) ^ 1 would work too. Oh, I guess b = b ^ 1 would work for positive integers, but it'd be problematic for big integers.)
At the question author's request:
The most compact way to achieve it is
b = Math.ceil(a) | 1;
First use ceil() to obtain the smallest integer not smaller than a, then obtain the smallest odd integer not smaller than ceil(a) by doing a bitwise or with 1 to ensure the last bit is set without changing anything else.
To obtain the smallest odd integer strictly larger than a, use
b = Math.floor(a+1) | 1;
Caveats:
Bit-operators operate on signed 32-bit integers in Javascript, so the value of a must be smaller than or equal to 2^31-1, resp. strictly smaller for the second. Also, a must be larger than -2^31-1.
If the representation of signed integers is not two's complement, but ones' complement or sign-and-magnitude (I don't know whether Javascript allows that, Java doesn't, but it's a possibility in C), the value of a must be larger than -1 -- the result of Math.ceil(a) resp. Math.floor(a+1) must be nonnegative.
Not really shorter, but this is more legible:
a=5.4;
b=Math.ceil(a);
b = b % 2 ? b : b + 1;
Try this:
a = 5.4
b = Math.ceil(a)
b = b%2 == 0 ? b+1 : b
y = Math.ceil((x - 1)/2)*2 + 1
Execute fn on http://www.intmath.com/functions-and-graphs/graphs-using-jsxgraph.php
Without Math.ceil() it can be done so:
b = a + a % 2 | 0 + 1;
NB. I consider next odd number of 5.0 as 7.

Categories

Resources