Эффективно подсчитывать количество бит в целочисленном выражении в JavaScript

Скажем, у меня есть целое число я и хочу получить счет 1s в его двоичной форме.

В настоящее время я использую следующий код.

Number(i.toString(2).split("").sort().join("")).toString().length;

Есть ли более быстрый способ сделать это? Я думаю об использовании побитовых операторов. Любые мысли?

ПРИМЕЧАНИЕ. i находится в пределах 32-разрядного ограничения.

Ответ 1

Вы можете использовать стратегию из этой коллекции Bit Twiddling Hacks:

function bitCount (n) {
  n = n - ((n >> 1) & 0x55555555)
  n = (n & 0x33333333) + ((n >> 2) & 0x33333333)
  return ((n + (n >> 4) & 0xF0F0F0F) * 0x1010101) >> 24
}

console.log(bitCount(0xFF)) //=> 8

Ответ 2

Очень хороший, но медленный рекурсивный способ:

    function count1(n, accumulator=0) {
      if (n === 0) {
        return accumulator
      }
      return count1(n/2, accumulator+(n&1))
    }

console.log(count1(Number.MAX_SAFE_INTEGER));

Ответ 3

Ниже работает отлично с любым числом:

var i=8823475632,count=0;while (i=Math.floor(i)) i&1?count++:0,i/=2
console.log(count); //17

Ответ 4

Делая n = n & (n - 1) вы удаляете последний 1 бит в номере. В соответствии с этим вы можете использовать следующий алгоритм:

function getBitCount(n) {
  var tmp = n;
  var count = 0;
  while (tmp > 0) {
    tmp = tmp & (tmp - 1);
    count++;
  }
  return count;
}

console.log(getBitCount(Math.pow(2, 10) -1));

Ответ 5

Учитывая, что вы создаете, сортируете и присоединяете массив, если он буквально быстрее вы хотите, вам, вероятно, лучше делать это скучно:

console.log(countOnes(8823475632));

function countOnes(i) {
  var str = i.toString(2);
  var n;
  var count = 0;
  for (n = 0; n < str.length; ++n) {
    if (str[n] === "1") {
      ++count;
    }
  }
  return count;
}

Ответ 6

Вы можете пропустить Number, sort и второй toString. Используйте filter, чтобы рассмотреть только 1 (истинное значение) в массиве, а затем получить, сколько из них прошли через length.

i.toString(2).split('').filter(v => +v).length