Where Would I Use a Bitwise Operator in JavaScript

Where would I use a bitwise operator in JavaScript?

Example:

Parses hexadecimal value to get RGB color values.

var hex = 'ffaadd';
var rgb = parseInt(hex, 16); // rgb is 16755421

var red = (rgb >> 16) & 0xFF; // returns 255
var green = (rgb >> 8) & 0xFF; // 170
var blue = rgb & 0xFF; // 221

~ bitwise operator in JavaScript

Under the covers, when Javascript does bitwise operations, it converts to a 32-bit signed integer representation, and uses that, then converts the result back into its internal decimal representation.

As such, your input value, 010001 becomes 00000000 00000000 00000000 00010001.

This is then inverted:

~00000000 00000000 00000000 00010001 => 11111111 11111111 11111111 11101110

Converted into hex, the inverted value is 0xFFFFFFEE, which is equivalent to the decimal value of -18.

Since this is a signed integer with a value of -18, this value is converted to the underlying decimal representation of -18 by Javascript.

When Javascript tries to print it as a base-2 number, it sees the negative sign and the value of 18, and prints it as -10010, since 10010 is the binary representation of positive 18.

Bitwise operators in JavaScript as flags on a state

You can't use bitwise operations like this with values that are not powers of 2.

The value 3 could be any of the follwing values:

  • CURRENT
  • COMPLETE | INCOMPLETE
  • CURRENT | COMPLETE
  • CURRENT | INCOMPLETE
  • CURRENT | COMPLETE | INCOMPLETE

There's no way to tell which combination it is.

Change the values to

  • COMPLETE = 1
  • COMPLETE = 2
  • CURRENT = 4
  • NOT_APPLICABLE = 8

and it's so easy to do bitwise operations with powers of 2.

Using bitwise operators in javascript

As previous answers explained, the bitwise operators are 32 bit signed. Thus, if at any point along the way you set bit 31, things will go badly wrong.

In your code, the expression

(upper_word<<16) | lower_word)

is evaluated first because of the parentheses, and since upper_word has the top bit set, you will now have a negative number (0x80000000 = -2147483648)

The solution is to make sure that you do not shift a 1into bit 31 - so you have to set bit 15 of the upper word to zero before shifting:

mask15 = 0x7fff;
((upper_word&mask15)<<16|lower_word)

This will take care of "numbers that are too big become negative", but it won't solve the problem completely - it will just give the wrong answer! To get back to the right answer, you need to set bit 31 in the answer, iff bit 15 was set in upper_word:

bit15 = 0x8000;
bit31 = 0x80000000;
answer = answer + (upper_word & bit15)?bit31:0;

The rewritten function then becomes:

function join_bitmap(hex_lower_word, hex_upper_word)
{
var lower_word = parseInt(hex_lower_word, 16);
var upper_word = parseInt(hex_upper_word, 16);
var mask15 = 0x7fff;
var bit15 = 0x8000;
var bit31 = 0x80000000;
return 0xffffffff & (((upper_word&mask15)<<16) | lower_word) + ((upper_word & bit15)?bit31:0);
}

There isn't just a single "hard coded special case" - there are 2 billion or so. This takes care of all of them.

Javascript: bitwise in VueJS?

This operator is called pipe and what you see here is an example of Vue filters. The value on the left passed through the pipe to functions on the right, the final value is then displayed. It is often used to format value in a desired way.

JavaScript -- pass a boolean (or bitwise) operator as an argument?

You can create a object with keys as operators and values as functions. You will need Bracket Notation to access the functions.

You can use Rest Parameters and some() and every() for more than two parameters for &&,||.

For the bitwise operator or +,-,*,/ multiple values you can use reduce()

const check = {  '>':(n1,n2) => n1 > n2,  '<':(n1,n2) => n1 < n2,  '&&':(...n) => n.every(Boolean),  '||':(...n) => n.some(Boolean),  '&':(...n) => n.slice(1).reduce((ac,a) => ac & a,n[0])}
console.log(check['>'](4,6)) //falseconsole.log(check['<'](4,6)) /trueconsole.log(check['&&'](2 < 5, 8 < 10, 9 > 2)) //true
console.log(check['&'](5,6,7) === (5 & 6 & 7))

Go returns other sum using bitwise operator than javascript

Integers in Javascript are 32-bit, while Go's int is architecture dependent, may be 32 bit and 64 bit. It's 64-bit on the Go Playground. And since each iteration shifts left by 5, using more than 6 characters surely "overflows" in Javascript (but not yet in Go): 7*5=35 > 32 bits.

Use explicit 32-bit integers (int32) to have the same output as in Javascript:

func CountChars(char string) int32 {
var sum int32 = 0
if char == "" {
return sum
}
for x := 0; x < len(char); x++ {
sum = (sum << 5) - sum + int32(char[x])
sum &= sum
}
return sum
}

This way output will be the same as that of Javascript (try it on the Go Playground):

2138589785
1871773944

Also note that Go stores strings as their UTF-8 byte sequences in memory, and indexing a string (like char[x]) indexes its bytes, the UTF-8 sequence. This is fine in your example as all the input characters are encoded using a single byte, but you'll get different result if the input contains multi-byte characters.

To properly handle all cases, use a simple for range over the string: that returns the successive runes, which is also an alias to int32, so you get the code points you need.

Also that check for empty string is unnecessary, if it's empty, the loop body will not be executed. Also sum &= sum: this is a no-op, simply remove this.

The simplified version:

func CountChars(s string) (sum int32) {
for _, r := range s {
sum = (sum << 5) - sum + r
}
return
}

Testing it:

fmt.Println(CountChars("Google 世界"))

Will output the same as in Javascript (try this one on the Go Playground):

-815903459

Why do I need a bit wise Operator to access the last array element?

You don't need a bitwise operator explicitly, you just need to convert it to an integer. As mentioned in comments, it's just one way of triggering a cast of a string into an integer.

typeof('str' | 0) === 'number'

But that sucks, right, since 'str' there is probably a bug. I'd be more explicit and use:

let a = parseInt(firstArr[i], 10);

That will return NaN if it is not a valid integer, and NaN === NaN is false, so you won't accidentally add it to newArr.

What is the different of bitwise operation between javascript and java

In javascript, you can perform bitwise operations on 32-bit numbers only. Even javascript use IEEE 754 floating-point standard to represent the number. Bitwise operation can be performed on 32-bit number. Hence rest of the bits will get ignored.

To convert any number to its 32-bit representation, number | 0 with it. When javascript reads x & y it considers 32-bits of x and y and ignores other bits silently. In your case, the numbers on which you are performing bitwise are x = -271733879 and y = -1732584194.

The safe range for bitwise operations in Javascript is Math.pow(-2,31) (-2147483648, about -2.1 billion) to Math.pow(2,32)-1 (2147483647, about +2.1 billion).

x= 4023233417;console.log(x.toString(2))y = 2562383102 ;console.log(y.toString(2));
result = x & y;
console.log(result.toString(2)); //-1110111011101110111011101111000
x = x | 0; //-271733879y = y | 0; //-1732584194console.log("32 bit x: " + x);console.log("32 bit y: " + y);result = x & y;
console.log(result.toString(2)); //-1110111011101110111011101111000

How does bitwise-and operator work on objects in javascript?

The intent of the deep variable is to detect the difference between these two calls:

Extend({keyA: {a: 1}, keyB: 2}, {keyC: 3, keyA: {b: 2}});

and

Extend(true, {keyA: {a: 1}, keyB: 2}, {keyC: 3, keyA: {b: 2}});

The first variant will return this:

{keyA: {b: 2}, keyB: 2, keyC: 3}

The second is intended to return this:

{keyA: {a: 1, b: 2}, keyB: 2, keyC: 3}

So the function in fact allows for a first, optional argument, that will make the function apply the extension recursively so you get a deep instead of a shallow extended object.
You can also see this intent by analysing the recursive call, where the first argument is deep, the second is the object to extend, and the third the object to extend with.
The following line also shows this:

var i = 1 + deep;

As i is point where the loop will start from, you can see that if deep is set to 1 instead of 0, the loop will start processing from argument #2 onwards, which makes sense, as argument #0 was recognised as being the optional argument, and the next one is the target object.
Note that the function accepts a variable number of additional arguments which it will use to extend the target object with. It is over these arguments that the i variable loops.

As a side note: because of a bug, the second version returns the same as the first. To fix the bug, replace

target[propName] = (deep && IsPlainObject(target[propName]))
? Extend(deep, {}, propValue) : propValue;

with:

target[propName] = (deep && IsPlainObject(target[propName]))
? Extend(deep, target[propName], propValue) : propValue;

Now, coming to the essence:

var deep = 1 & args[0];

The use of the bitwise operator must have been an idea to have efficiency rule over clarity. The intent was to set deep to 1 if the first argument represented the optional argument, which should be a boolean indicating whether the extending should happen shallow or deep. As objects will make this expression evaluate to 0, it seemed like a nice trick.
But there is an issue with this. If one would like to do this:

Extend(["3"], {myattr: 2});

One would expect to get back an array-like object with an additional custom property myattr:

{0: "3", length: 1, myattr: 2}

However, the current Extend function will misinterpret the first argument as an instruction to perform a deep extension. This is because
1 & ["3"] will evaluate to 1 & 3, which evaluates to 1. And so the result will be the second argument without any extension happening:

{myattr: 2}

Conclusion: it is better to avoid such cryptic use of bitwise operators, and do something like this:

var deep = args.length > 0 && typeof args[0] === 'boolean' && args[0];

In common language: let deep be true (1) when there is at least one argument and that argument is a boolean and its value is true. In all other cases let it be false (0).
Note that one cannot pass false as the first argument, thinking that it will make the function perform a shallow extension. In this case,
that argument will be taken as the object to extend, which will fail. So the optional first argument, if provided, must be a boolean with value true.
This is true both for the original Extend function and the corrected one.

Finally, it would be good to add comments to this function to clarify the use of the first optional argument.



Related Topics



Leave a reply



Submit