What does this symbol mean "&="? [duplicate] - javascript

This question already has answers here:
What do these JavaScript bitwise operators do?
(3 answers)
Closed 6 years ago.
function ArithGeo(arr) {
var diff = arr[1]-arr[0];
var ratio = arr[1]/arr[0];
var allRatioAreGood = true;
var allDiffAreGood = true;
for(var i = 2;i<arr.length;i++){
// console.log(arr[i]-arr[i-1] == diff);
allRatioAreGood &= (arr[i]/arr[i-1] == ratio);
allDiffAreGood &= (arr[i]-arr[i-1] == diff);
}
// code goes here
if (allRatioAreGood){
return "Geometric"
}else if (allDiffAreGood){
return "Arithmetic";
}else {
return -1
}
}
console.log(ArithGeo([2, 4, 6, 7 , 8 ,10]));
what does '&=' mean when we used it in the for loop? and how does it work? can someone explain please?
also, how does those two lines work?
allRatioAreGood &= (arr[i]/arr[i-1] == ratio);
allDiffAreGood &= (arr[i]-arr[i-1] == diff);
Can anyone explain please ?

It is the bitwise AND assignment.
In your code example, let's take a look at the first one:
allRatioAreGood &= (arr[i]/arr[i-1] == ratio);
the values arr[i] and arr[i-1] are divided by each other (producing a ratio), and that ratio is tested for equality (using ==), producing a true or false value.
That value is then bitwise AND-ed to the existing value of allRatioAreGood, which means that if the previous value for allRatioAreGood was false (binary 0), then all future values for allRatioAreGood would also result in false (because of the AND operation, 0 & 1 = 0).
The result of this is that allRatioAreGood and allDiffAreGood figures out if all of the values in that array pass that test for equality, that is, if all the values have that "good ratio" or "good difference".
However, in this particular example, the comparator is checking for equality between a ratio and the result of a division, meaning that because the result of a division operation is a floating point number, no other number would be equal to it when testing with ==. To test for "close enough equals", an epsilon needs to be used. See this other SO answer for more info: What's wrong with using == to compare floats in Java? (don't worry that this is Java vs. JavaScript, the concept is the same). Additionally, this gets even more complicated because in Javascript, if the result of ratio or the division operation is NaN or Infinity, you will always get false when comparing the two numbers.
From the docs:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators
Bitwise AND assignment
The bitwise AND assignment operator uses the binary representation of both operands, does a bitwise AND operation on them and assigns the result to the variable. See the bitwise AND operator for more details.
Syntax
Operator: x &= y Meaning: x = x & y
Example
var bar = 5;
// 5: 00000000000000000000000000000101
// 2: 00000000000000000000000000000010
bar &= 2; // 0

a &= b;
is the same as saying:
a = a & b;
So why use this form? Maybe you have a more complex expression, and want to make is clear that a and a are the same lvalue:
obj.array[index].bits = obj.array[index].bits & mask;
versus:
obj.array[index].bits &= mask;

Its a bitwise operator:
result = expression1 & expression2
a &= b; is equivalent to a = a & b;
MDN Docs on bitwise operators

Bitwise AND assignment, pretty much if you have 5 & 3, the use of bitwise converts the numbers to base 2, which is 00101 & 00011 (many more 0's in front) and get 1 because the one's digit's are both 1 (true)
Generally, && is a multiplication, where || is addition, same goes for bitwise, 1 & 1 is 1 * 1 and 1 | 1 is 1 + 1 which is truthy (even though it's still considered a 1..)

Related

Bitwise OR ( | ) and Bitwise Operator ( ~ ) - Javascript

The challenge: Given integers N and K (where 2 <= K <= N), find the highest value of A & B (i.e. A bitwise-AND B) such that 0 <= A < B <= N and (A & B) < K.
I've made my code and it runs perfect with visible cases but it fails with the hidden cases.
My Code:
function bitwiseAnd(N, K) {
// Write your code here
let arr = []
N = parseInt(N,10)
K = parseInt(K,10)
for(let a=1; a<N; a++){
for(let b=a+1; b<=N ; b++){
if(K>=0 && parseInt(a&b,10) < K && parseInt(a&b,10)>=0) arr.push(parseInt(a&b,10))
}
}
return Math.max(...arr)
}
i searched for a solution and i found this one.
Solution:
function bitwiseAnd(N, K) {
// Write your code here
var n = parseInt(N);
var k = parseInt(K);
var a = k - 1;
var b = (~a) & -(~a);
if ( (a | b) > n )
return(a - 1);
else
return(a);
}
However the solution's code is working good with all hidden test, i cannot understand how it works, as i'm not familiar with Bitwise operators.
is there any chance to get an explanation of this operators and how to use ?
Thanks in advance.
Here is a variant of your code that works:
function bitwiseAnd(N, K) {
let r = 0;
for(let a=1; a<N; a++) {
for(let b=a+1; b<=N; b++) {
if((a&b) < K) r = Math.max(r, a&b)
}
}
return r
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
I've removed unnecessary parseInts and result checks. However, the only thing that was actually wrong with your code was the line Math.max(...arr).
The problem with that line is that it is not passing a reference to arr to the Math.max method. Instead, it is actually including all members of arr as arguments which will appear on the Javascript call stack. Normally, this would be fine. However, if you have hundreds of thousands of values in the array, the maximum call stack size will be exceeded and your code will fail to execute. This is why a hidden test case, which must have resulted in huge numbers of array members, caused hackerrank to reject your solution.
You've also posted a very interesting solution which does not use loops at all.
I've cleaned it up a little, and included it below:
function bitwiseAnd(n, k) {
let a = k-1
return (a | ~a & a+1) <= n ? a : a-1
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
Note that the original code said & -(~a) instead of & a+1. The Two's complement method of negating a number is to flip all bits and add one to the result. Since the bitwise not ~ also means to flip all bits, the original code flips all bits, flips all bits again, and then adds one. This is therefore an obfuscation of simply doing a+1.
Here is an explanation of the thinking that must be behind that code:
Since the result of A & B must be less than K, the maximum number that might be the result will be K-1.
When we do the bitwise A & B, the result can only switch certain bits off, and cannot switch any bits on. Since A must be a smaller number than B, and since we can only switch bits of A off, the result of A & B thus cannot exceed the value of A.
Combining the two conclusions above, we can conclude:
The choice of A cannot exceed K-1 if our choice of B will preserve all bits of A.
So, let's see if we can set A to K-1 and find a value of B which will preserve all bits in A.
The first value greater than A that will preserve all bits of A will be the result of setting the least significant bit that is currently unset.
For example, if A = 101, the next value of B that will preserve all bits of A after doing A & B is 111.
In order to locate the position of the least significant unset bit, we can do ~A & A+1. For the example where A is 101, ~A & A+1 is 010. Essentially, ~A & A+1, no matter what the value of A, will always return a binary sequence containing exactly one set bit.
The reason this works is that ~A acts as a mask that will only allow the result of ~A & A+1 to contain bits which were unset in A. When we do A+1, the first bit that will be set for the first time in A will be the least significant unset bit, and no other bits will be set for the first time.
For example: if A = 101, ~A = 010, A+1 = 110, and so ~A & A+1 = 010 & 110 = 010. That 1 in the answer is the position of the least significant unset bit in A.
If we do a bitwise OR, we can use this result to calculate the first higher value of B which will preserve all bits of A. Thus B = A | ~A & A+1. Therefore, we can see in the runnable code snippet above that if we find that (a | ~a & a+1) <= n, we know that the value of a = k-1 will work and we can return this as the answer.
But, what if that value of B that exceeds N? We will need to find the next-best answer.
Since we tried A = K-1, and since the question states K <= N, this means A must have been an odd number (i.e. the least significant bit was set). This is because if A was even, we'd have attempted the value B = A + 1, and B could not have exceeded N since K <= N and A = K-1.
So, since our earlier attempt failed when we tried A = K-1, we know we can't go higher than A to find a value of B that works when A = K-1.
But, if we set A = K-2, and since we know K-1 was odd, this means K-2 is even. This means that we can have A = K-2 and B = K-1, and A & B = K-2. The result of the function is therefore K-2.
The code could therefore perhaps be more clearly written as:
function bitwiseAnd(n, k) {
let a = k-1
return (a | ~a & a+1) <= n ? k-1 : k-2
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
The bottom line is that we don't need any loops, because there is always an answer where A = K-1 and B is more than one higher than A, or where A = K-2 and B = K-1.
But, there is an improvement we can make...
So far, we've explained the thinking behind the solution you posted. That solution, however, is more complicated than it needs to be.
If we want to take A and set the least-significant unset bit, we can simply do A | A+1.
This means a simpler solution would be:
function bitwiseAnd(n, k) {
let a = k-1
return (a | a+1) <= n ? k-1 : k-2
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
And, if we really want to code-golf the solution, we can substitute out the variable a, and take advantage of Javascript coercing true/false to 1/0 and do:
function bitwiseAnd(n, k) {
return --k-((k++|k)>n)
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0

Unambiguous increment and adding results in error

When playing around with JavaScript syntax it struck me that the following code will throw an error in SpiderMonkey and V8 engines:
var a = 1, b = 1;
a++++b;
This to me is strange, since the following works perfectly fine:
var a = 1, b = 1;
a+++b; // = 2; (Add a and b, then increase a)
// now a == 2 and b == 1
a+++-b; // = 1; (add a and -b, then increase a)
// now a == 3 and b == 1
In addition, the following would be nonsensical code:
var a = 1, b = 1;
a++ ++b; // throws an error
My argument is now that if a+++b is equivalent to a++ + b, and not to a+ ++b, and a+++-b is equivalent to a++ + -b, then a++++b can only be interpreted as a++ + +b in order for it to be valid JavaScript code.
Instead, the engines insist that a++++b is interpreted as a++ ++b, by operator precedence.
This to me is in contrast with the logic that the engines implements using the / symbol, as explained here, to distinguish between division and regular expressions. An example
var e = 30, f = 3, g = 2;
e/f/g; // == 5
e
/f/g; // == 5
/f/g; // is equivalent to new RegExp("f","g")
Here the argument is that because /f/g does not make sense as division in the last line, it is interpreted as a regular expression.
Obviously the / symbol gets a special treatment, in order to distinguish between division and regular expressions. But then why do ++ and -- not get a special treatment as well? (That is, outside operator precedence)
A second question is why operator precedence is not called only when the code is has multiple valid interpretations.
In the code a++++b you have two distinct statements: a++ and ++b with nothing to combine them. The + operator in the context of a++ + +b is actually a type converter (meant for turning strings into numbers) and has a different order of precedence which follows the others in the list.

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

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

Javascript: Comparing two float values [duplicate]

This question already has answers here:
Javascript float comparison
(2 answers)
Closed 6 months ago.
I have this JavaScript function:
Contrl.prototype.EvaluateStatement = function(acVal, cfVal) {
var cv = parseFloat(cfVal).toFixed(2);
var av = parseFloat(acVal).toFixed(2);
if( av < cv) // do some thing
}
When i compare float numbers av=7.00 and cv=12.00 the result of 7.00<12.00 is false!
Any ideas why?
toFixed returns a string, and you are comparing the two resulting strings. Lexically, the 1 in 12 comes before the 7 so 12 < 7.
I guess you want to compare something like:
(Math.round(parseFloat(acVal)*100)/100)
which rounds to two decimals
Compare float numbers with precision:
var precision = 0.001;
if (Math.abs(n1 - n2) <= precision) {
// equal
}
else {
// not equal
}
UPD:
Or, if one of the numbers is precise, compare precision with the relative error
var absoluteError = (Math.abs(nApprox - nExact)),
relativeError = absoluteError / nExact;
return (relativeError <= precision);
The Math.fround() function returns the nearest 32-bit single precision float representation of a Number.
And therefore is one of the best choices to compare 2 floats.
if (Math.fround(1.5) < Math.fround(1.6)) {
console.log('yes')
} else {
console.log('no')
}
>>> yes
// More examples:
console.log(Math.fround(0.9) < Math.fround(1)); >>> true
console.log(Math.fround(1.5) < Math.fround(1.6)); >>> true
console.log(Math.fround(0.005) < Math.fround(0.00006)); >>> false
console.log(Math.fround(0.00000000009) < Math.fround(0.0000000000000009)); >>> false
Comparing floats using short notation, also accepts floats as strings and integers:
var floatOne = 2, floatTwo = '1.456';
Math.floor(floatOne*100) > Math.floor(floatTwo*100)
(!) Note: Comparison happens using integers. What actually happens behind the scenes: 200 > 145
Extend 100 with zero's for more decimal precision. For example use 1000 for 3 decimals precision.
Test:
var floatOne = 2, floatTwo = '1.456';
console.log(Math.floor(floatOne*100), '>', Math.floor(floatTwo*100), '=', Math.floor(floatOne*100) > Math.floor(floatTwo*100));
Comparing of float values is tricky due to long "post dot" tail of the float value stored in the memory. The simplest (and in fact the best) way is: to multiply values, for reducing known amount of post dot digits to zero, and then round the value (to rid of the tail).
Obviously both compared values must be multiplied by the same rate.
F.i.: 1,234 * 1000 gives 1234 - which can be compared very easily. 5,67 can be multiplied by 100, as for reducing the float comparing problem in general, but then it couldn't be compared to the first value (1,234 vel 1234). So in this example it need to be multiplied by 1000.
Then the comparition code could look like (in meta code):
var v1 = 1.234;
var v2 = 5.67;
if (Math.round(v1*1000) < Math.round(v2*1000)) ....

Categories

Resources