How do Bitwise Operators work? - javascript

So I was going through some problems at codewars.com and I came across a problem about basic encryption (https://www.codewars.com/kata/basic-encryption/javascript). The goal is to get a string value and shift it x values to the right on the ASCII chart.
here was my initial solution:
function encrypt(text, rule) {
let res = ''
for(let i = 0; i<text.length; i++) {
res += (String.fromCharCode(text.charCodeAt(i)+rule))
}
return res
};
However, it didn't pass all of the tests, so I looked at the solutions and this is what got me to pass the tests:
function encrypt(text, rule) {
let res = ''
for(let i = 0; i<text.length; i++) {
res += (String.fromCharCode(text.charCodeAt(i)+rule & 255))
}
return res
};
All because of adding that & 255, Could someone explain to me what has really changed by adding that to make my code valid?

As somebody said above, your valid range of characters is from 0 to 255. There are many ways to valid this condition but bitwise and looks like shortest one.
Bitwise AND returns a one in each bit position for which the corresponding bits of both operands are ones.
For example:
1111 & 0000 would return 0000
1111 & 0001 would return 0001
1111 & 0010 would return 0010
1111 & 0100 would return 0100
But, as you can read in the docs:
Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values.
If you use this operator on integer you would get integer instead of binary.
In your case, using number & 255 makes you sure that end value would be in range from 0 to 255.
You can read more about bitwise operators there.

Related

How does ~5 return -6?

I am asking this question as a follow up to my previous question.
The page at W3chools says:
The examples above uses 4 bits unsigned binary numbers. Because of this ~ 5 returns 10.
Since JavaScript uses 32 bits signed integers, it will not return 10.
It will return -6. 00000000000000000000000000000101 (5)
11111111111111111111111111111010 (~5 = -6)
A signed integer uses the leftmost bit as the minus sign.
Inverting the bits and chopping off the sign bit, the number becomes 1111111111111111111111111111010, which evaluates to 2147483642 in decimal form. According to the page, however, it should evaluate to -6.
Where did I go wrong?
The mistake lies in "chopping off the sign bit" of the 32 bit complemented result. This converts -6 (which has lots of leading 1s in it's binary representation) into a 31 bit positive number which still has lots of leading 1s in its binary representation. The 31 bit number obtained by removing the sign bit from -6 is very close to the maximum positive value of a 32 bit signed number.
You can see the results without removing the 32 bit integer sign bit:
function unsignedNibble( i) {
return i & 0x0f;
}
function signedNumberBits( n) {
var bits = "";
for( var i = 32; i--;) {
bits = "" + (n&1) + bits;
n = n >> 1;
}
return bits;
}
console.log("Unsigned 4 bit: ");
var un5 = unsignedNibble( 5); // unsigned 4 bits of 5
console.log( "un5 = %s ( 0b%s)", un5, un5.toString(2));
var notUn5 = unsignedNibble( ~un5);
console.log( "~un5 = %s ( 0b%s)", notUn5, notUn5.toString(2));
console.log("Signed 32 bit: ");
var sn5 = 5; // signed number 5
console.log( "sn5 = %s ( 0b%s)", sn5, sn5.toString(2));
var notSn5 = ~sn5;
console.log( "~sn5 = %s ( 0b%s)", notSn5, signedNumberBits(notSn5));
#wais
6 is represent as 0000 0110 (0 has been padded)
now to get -6 we have to make 2's Complement for that
Step 1 - Reverse all the bits (1st Complement)
1111 1001
Step 2 - Add 1 (0000 0001)
1111 1001 + 0000 0001 = 1111 1010
In 2's compliment, you add 1 at the end after the bits are all complimented to get the negative number's absolute value.
1111111111111111111111111111010 is complimented to get ...0101 (which is 5), but then you add 1 to get 6. Remembering this was a negative number you're determining, you slap the negative sign on to get -6.
JavaScript binary numbers are stored in two's complement format.
This means that a negative number is the bitwise NOT of the number plus 1. For example:
Binary Representation Decimal value
00000000000000000000000000000101 5
11111111111111111111111111111011 -5
00000000000000000000000000000110 6
11111111111111111111111111111010 -6
00000000000000000000000000101000 40
11111111111111111111111111011000 -40
Source: https://www.w3schools.com/js/js_bitwise.asp
~ operator just do bit change.
such as ~5 = ~(00000101) it returns (11111010) = -6
Don't make ~ operator too complicated.

I don't understand what is happening with this XOR

I am working on this problem.
"Given an array, find the int that appears an odd number of times.
There will always be only one integer that appears an odd number of times."
I came up with this solution online:
function findOdd(A) {
var n = 0;
for(var i = 0; i < A.length; i++){
n = n^A[i];
}
return n;
}
This works but I am not sure why and i was hoping someone could explain it to me. I just don't understand the line:
n = n^A[i];
Could you please tell me what it is doing in this instance?
Xoring any number with itself will result in 0. If you know that there's only one number that appears an odd number of times, the others will cancel themselves out by self-xoring, and the answer will be the remaining number that appears an odd number of times.
XOR of two same numbers is always zero. That is,
A^A=0
So, if you XOR a particular number with itself repeatedly for even number of times, the result will be zero.
Here, initially the value of n is zero. The number that will be XOR-ed even number of times, will result zero. And the number that is present odd number of times, say 2m+1number of times, will result in zero for 2m occurrences, and that same number for the final one occurrence.
This is how this solution works.
^ is an exor bit wise operator . so when you do
1 ^ 1 is 0
0 ^ 1 is 1
1 ^ 0 is 1
0 ^ 0 is 0
so to find the odd number of 1's the following code does is
initially result is arr[0] is 1 .
so in the arrary 0^ 0 becomes 0 and 2 ^ 2 becomes 0 and there are 3 1's so 1^1 gets 0 and with 0 ^1 we are leftout with the number which repeats odd nubmer of times
var arr=[1,1,1,0,0,2,2];
var result=arr[0];
for(var i=1;i<arr.length;i++)
result=result ^ arr[i];
console.log(result);
Hope it helps
Bitwise operators work on 32 bits numbers. Any numeric operand in the operation is converted into a 32 bit number. The result is converted back to a JavaScript number. ^ is a bitwise XOR javascript operator.
Bitwise XOR Operator returns a one in each bit position for which the corresponding bits of either but not both operands are ones.
a XOR b yields 1 if a and b are different. The truth table for the XOR operation is:
a b a XOR b
0 0 0
0 1 1
1 0 1
1 1 0
Explanation for expression n = n^A[i];
let A = [1,2,3,4,5]
for n=0, i=0 => 0 ^ A[0] => 0 ^ 1 => converted to binary 0000 ^ 0001 results to 0001 which is equal to 1
for n=1, i=1 => 1 ^ A[1] => 1 ^ 1 => converted to binary 1111 ^ 0010 results to 1101 which is equal to 13
and so on... Hope this solution helps you to understand the above expression and clear your all doubts.

How can I check that a bit is set (without bitwise operation)?

Looking at the int 44 — I need Math.CEIL (log(2) 44) of binary places to represent 44.
(answer is 6 places)
6 places :
___ ___ ___ ___ ___ ___
32 16 8 4 2 1
But how can I check that (for example) the bit of 8 is checked or not ?
A simple solution will be do to :
((1<<3) & 44)>0 so this will check if the bit is set.
But please notice that behind the scenes the computer translates 44 to its binary representation and just check if bit is set via bitwise operation.
Another solution is just to build the binary myself via toString(2) or mod%2 in a loop
Question
Mathematically Via which formula, I can test if n'th bit is set ?
(I would prefer a non loop operation but pure single math phrase)
Divide by the value of the bit that you want to check
and test if the first bit is set (this can be tested with x mod 2 == 1)
Math expression:
floor(value/(2^bitPos)) mod 2 = 1
As JS function:
function isSet(value, bitPos) {
var result = Math.floor(value / Math.pow(2, bitPos)) % 2;
return result == 1;
}
Note: bitPos starts with 0 (bit representing the nr 1)
The 'bit' (actually any base) value of an indexed number index in a value val in base base can in general be calculated as
val = 1966;
index = 2;
base = 10;
alert (Math.floor(val/Math.pow(base,index)) % base);
result: 9
val = 44;
index = 3;
base = 2;
alert (Math.floor(val/Math.pow(base,index)) % base);
result: 1 (only 0 and 1 are possible here – the range will always be 0..base-1).
The combination of Math.floor (to coerce to an integer in Javascript) and Math.pow is kind of iffy here. Even in integer range, Math.pow may generate a floating point number slightly below the expected 'whole' number. Perhaps it is safer to always add a small constant:
alert (Math.floor(0.1+val/Math.pow(base,index)) % base);
You can simply check if the bit at the position is set to 1.
function isBitSet(no, index) {
var bin = no.toString(2);
// Convert to Binary
index = bin.length - index;
// Reverse the index, start from right to left
return bin[index] == 1;
}
isBitSet(44, 2); // Check if second bit is set from left
DEMO

checking decimal floating point number

Normally we expect 0.1+0.2===0.3 to be true. But it is not what javascript will result. As javascript displays decimal floating point number but stores binary floating point number internally. So this returns false.
If we use chrome developer tool console, we'll get the following result:
0.1+0.2;//0.30000000000000004
0.1+1-1;//0.10000000000000009
0.1 + 0.2 === 0.3 ;// returns false but we expect to be true.
0.1+1-1===0.1;//returns false
Due to rounding errors, as a best practice we should not compare non-integers directly. Instead, take an upper bound for rounding errors into consideration. Such an upper bound is called a machine epsilon.
And here is the epsilon method:
var eps = Math.pow(2,-53);
function checkEq(x,y){
return Math.abs(x - y) < eps;
}
Now, if we check it returns true.
checkEq(0.1+0.2,0.3);// returns true
checkEq(0.1+1-1,0.1);//returns true
It's okay and fine. But if I check this:
checkEq(0.3+0.6,0.9);// returns false
Which is not okay and not as what we expect.
So, how should we do to return the correct results?
What I've tried to solve this is like this:
var lx,ly,lxi,lyi;
function isFloating(x){
return x.toString().indexOf('.');
}
function checkEq(x,y){
lxi = x.toString().length - x.toString().indexOf('.') - 1;
lyi = y.toString().length - y.toString().indexOf('.') - 1;
lx = isFloating(x) > -1 ? lxi : 0;
ly = isFloating(y) > -1 ? lyi : 0;
return x.toFixed(lx) - y.toFixed(ly)===0;
}
Now, fixed. And it results fine if I check like this:
checkEq(0.3,0.3); //returns true
But the following returns false
checkEq(0.3+0.6,0.9)
As here first it's value is stored in binaray floating point number and then returning decimal floating point number after calculating.
So now, how can I set toFixed() method for each input like in checkEq(0.3+0.6,0.9) 0.3.toFixed(lx) and 0.6.toFixed(lx) and then only add:
var lx,ly,lxi,lyi;
function isFloating(x){
return x.toString().indexOf('.');
}
function checkEq(x,y){
x = x.toString().split(/\+ | \- | \/ | \ | \\ */);
y = x.toString().split(/\+ | \- | \/ | \ | \\*/);
for(var i=0;i<x.length,y.length;i++){
//here too I may be wrong...
lxi = x[i].toString().length - x[i].toString().indexOf('.') - 1;
lyi = y[i].toString().length - y[i].toString().indexOf('.') - 1;
// particularly after this would wrong...
lx = isFloating(x[i]) > -1 ? lxi : 0;
ly = isFloating(y[i]) > -1 ? lyi : 0;
//And, here I'm stucked too badly...
//take splitted operators to calculate:
//Ex- '0.3 + 1 - 1'
// Number('0.3').toFixed(1) + Number('1').toFixed(0) - Number('1').toFixed(0)
//But careful, we may not know how many input will be there....
}
//return x.toFixed(lx) - y.toFixed(ly)===0;
}
Other answers are also welcome but helping me with my code is greatly appreciated.
Perhaps you should try out some existing JS Math library such as bignumber.js, which supports arbitrary-precision arithmetic. Implementing everything from scratch will be rather time consuming and tedious.
Example
0.3+0.6 //0.8999999999999999
x = new BigNumber('0.3') // "0.3"
y = new BigNumber('0.6') // "0.6"
z = new BigNumber('0.9') // "0.9"
z.equals(x.plus(y)) // true
I think you should take a little larger value for epsilon.
You can also have a look at math.js: the comparison functions of math.js also check for near equality. Comparison is explained here:
http://mathjs.org/docs/datatypes/numbers.html#comparison
So you can do:
math.equal(0.1 + 0.2, 0.3); // true
math.equal(0.3 + 0.6, 0.9); // true
even better, math.js has support for bignumbers (see docs), so you can do:
math.equal(math.bignumber(0.1) + math.bignumber(0.2), math.bignumber(0.3);
or using the expression parser:
math.config({number: 'bignumber'});
math.eval('0.1 + 0.2'); // returns BigNumber 0.3, not 0.30000000000000004
math.eval('0.1 + 0.2 == 0.3'); // returns true
Discontinuous functions such as equality (but also floor and ceil) are badly affected by rounding errors, and taking an epsilon into account may work in some cases, but may also give an incorrect answer (e.g. abs(x-y) < eps may return true while the exact value of x and y are really different); you should do an error analysis to make sure that it is OK. There is no general way to solve the problem in floating point: this depends on your application. If your inputs are decimal numbers and you just use addition, subtraction and multiplication, a decimal floating-point arithmetic may be OK if the precision is large enough so that all your data can be represented exactly. You can also use a rational arithmetic, such as big-rational (not tried).

Strange javascript operator: expr >>> 0 [duplicate]

This question already has answers here:
What is the JavaScript >>> operator and how do you use it?
(7 answers)
Closed 7 years ago.
the following function is designed to implement the indexOf property in IE. If you've ever had to do this, I'm sure you've seen it before.
if (!Array.prototype.indexOf){
Array.prototype.indexOf = function(elt, from){
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++){
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
I'm wondering if it's common to use three greater than signs as the author has done in the initial length check?
var len = this.length >>> 0
Doing this in a console simply returns the length of the object I pass to it, not true or false, which left me pondering the purpose of the syntax. Is this some high-level JavaScript Ninja technique that I don't know about? If so, please enlighten me!
>>> is the Zero-fill right shift operator. The >>> 0 is an abuse of the operator to convert any numeric expression to an "integer" or non-numeric expression to zero. Here is what it does:
This operator shifts the first operand the specified number of bits to
the right. Excess bits shifted off to the right are discarded. Zero
bits are shifted in from the left. The sign bit becomes 0, so the
result is always positive.
Here is an explanation of the convert-to-integer behavior which applies to all bitwise operations:
Bitwise operators treat their operands as a sequence of 32 bits (zeros
and ones), rather than as decimal, hexadecimal, or octal numbers.
[...] Bitwise operators perform their operations on such binary
representations, but they return standard JavaScript numerical values.
Together, these statements assert that expr >>> 0 will always return a positive number as follows:
expr is cast to a 32-bit integer for bitwise operation
>>> 0 has no effect (no bits are shifted)
The result is converted to a Number
Here are a few expressions and their outcome:
1 >>> 0 // 1 -- Number cast to 32-bit integer then back to Number
"1" >>> 0 // 1 -- String cast to 32-bit integer then back to Number
undefined >>> 0 // 0 -- failed cast yields zero
Other interesting cases:
1.1 >>> 0 // 1 -- decimal portion gets it
-1 >>> 0 // 4294967295 -- -1 = 0xFFFFFFFF
// Number(0xFFFFFFFF) = 4294967295
"A" >>> 0 // 0 -- cast failed
"1e2" >>> 0 // 100 -- 1x10^2 is 100
"1e10" >>> 0 // 1410065408 -- 1x10^10 is 10000000000
// 10000000000 is 0x00000002540BE400
// 32 bits of that number is 0x540BE400
// Number(0x540BE400) is 1410065408
Note: you will notice that none of them return NaN.
Source: LINK
This is the zero-fill right shift
operator which shifts the binary
representation of the first operand to
the right by the number of places
specified by the second operand. Bits
shifted off to the right are discarded
and zeroes are added on to the left.
With a positive number you would get
the same result as with the
sign-propagating right shift operator,
but negative numbers lose their sign
becoming positive as in the next
example, which (assuming 'a' to be
-13) would return 1073741820:
Code:
result = a >>> b;
The >>> (right-shift) binary operator is simply shifting the right-most bits of a number a specified number of times, and padding with zeroes to the left.
Note: In the following examples, the number in braces after a number signals what base it's in. 2 is for binary, 10 for decimal.
For example, 4 >>> 1 would do:
4(10) = 100(2)
4(10) >>> 1(10) = 010(2) = 2(10)
shift once to the right
Other examples:
4(10) >>> 2(10) = 100(2) >>> 2(10) = 001(2) = 1(10)
10(10) >>> 4(10) = 1010(2) >>> 4(10) = 0000(2) = 0(10)
15(10) >>> 1(10) = 1111(2) >>> 1(10) = 0111(2) = 7
The way I remember it is to move the necessary amount of bits to the right, and then write the number. Like, in the last example, I simply moved everything to the right once, so the result is 0111.
Shifting 0 times does...nothing. No idea why it's there.
Behold the zero-fill right-shift operator.
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Bitwise_Operators

Categories

Resources