4

I'm a bit confused after reading about how to use bitmasks to store boolean values. I would like to have a set of boolean values and then generate a unique integer for each combination of the values. Here is the current system so far:

var a = 1 << 1
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4

var uniqueint1 = getInt(true, false, false)
var uniqueint2 = getInt(true, true, false)
var uniqueint3 = getInt(true, true, true)
// ...

function getInt(x, y, z) {
  var value = a
  if (x) value = value | b
  if (y) value = value | c
  if (z) value = value | d
  return value
}

But the problem is, I am not sure if I am supposed to handle the "not" case, along the lines of this:

function getInt(x, y, z) {
  var value = a
  if (x) value = value | b
  else value = value ^ b

  if (y) value = value | c
  else value = value ^ c

  if (z) value = value | d
  else value = value ^ z

  return value
}

All I know is that I've seen |, &, and ^ related to bitmasks, and I know to find if a boolean is in the bitmask you do var yes = value & b, but I'm just confused how to generate the bitmask so that it handles both the if (true) and if (false) cases. Not sure if I'm supposed to be using ^ somewhere, or what else I'm doing wrong. Please advise. Thank you!

1
  • Can you be more specific on what you mean with the "not" case? Wouldn't that just be the negated form of "yes"? I also wonder what brings you into using the bitwise xor operator there. Commented Dec 20, 2017 at 21:42

3 Answers 3

7

I am not sure if I am supposed to handle the "not" case

You're not supposed to handle it at all. A bitmask works so that you either have a bit with value 1 if your flag is set or the bit with value 0 if not. Given that your value starts with 0s everywhere (the integer 0), you just have to set the bit (by OR 1) when your condition is true and you don't have to do anything otherwise.

You could simplify your code to

function getInt(x, y, z) {
  return (0b10 // a
          | (x << 2)   // 0b00100 if x and 0b00000 else
          | (y << 3)   // 0b01000 if y and 0b00000 else
          | (z << 4)); // 0b10000 if z and 0b00000 else
}
Sign up to request clarification or add additional context in comments.

Comments

2

A NOT op will invert the bit so it needs to be set in order to be cleared.

(Assuming you want to toggle bits on or off on an existing value:) You can use NOT together with a AND mask to clear off a bit like this:

var v = 0xff;            // value
var bit3 = 1<<3;         // the bit we want to clear

// clear bit 3:
v &= ~bit3;              // create a AND mask inverting bit 3 and AND with value
console.log(v.toString(2));

v &= ~bit3;              // will not set the bit even when already cleared
console.log(v.toString(2));

You can of course also check if the bit is set and then NOT it if it is:

var v = 0xff;
var bit3 = 1<<3;

if (v & bit3) v ^= bit3;   // NOT bit 3 if set
console.log(v.toString(2));

// should not trigger:
if (v & bit3) console.log("Whaa");

To set it instead, you would use OR regardless of the state:

if (v & bit3) v ^= bit3;   // NOT bit 3 if set
else {v |= bit3};          // set it not set already

If you need to clear several bits at once you can first OR the bits together, then use that with NOT for a AND mask:

var v = 0xff;
var bit1 = 1<<1;
var bit3 = 1<<3;

// create NOT mask:
var mask = bit1 | bit3;

// clear bits:
v &= ~mask;
console.log(v.toString(2));

So in the function you could so something like this:

var a = 0xff;
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4

function getInt(x, y, z) {
  var value = a;
  value = x ? value | b : value & ~b;
  value = y ? value | c : value & ~c;
  value = z ? value | d : value & ~d;
  return value
}

// turn off bit c/d (bit index 3 & 4):
console.log(getInt(true,false,false).toString(2));

// turn on c, off b/d
console.log(getInt(false,true,false).toString(2));

// with same value turn off all, then on c:
a = getInt(false, false, false);
console.log(getInt(false,true,false).toString(2));

2 Comments

Don't use 0xFF ^ bit3 to invert. Just use ~bit3 - which inverts all (in JS 32) bits, not just 8 of them.
@Bergi I forgot about that one.. thanks (OR I was thinking of C.. hmm). 0xff was me being lazy :)
0

By doing var value=1 at the beginning you are already setting value to 2, because 1<<1=2. I suggest you set value=0, and remove else value = value ^ c, since that operation does not cause any change when you start with all zeros. Your code would look as follows:

var a = 1 << 1
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4

function getInt(x, y, z) {
  var value = 0
  if (x) value = value | b
  if (y) value = value | c
  if (z) value = value | d
  return value
}

var uniqueint1 = getInt(true, false, false)
var uniqueint2 = getInt(true, true, false)
var uniqueint3 = getInt(true, true, true)
uniqueint1

This prints out 4, instead of 6 for uniqueint1.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.