Самый быстрый способ создать это число?

#javascript #bit-manipulation

#javascript #манипулирование битами

Вопрос:

Я пишу функцию для расширения числа со знаком до большей длины в битах. Это очень часто используемое действие в наборе команд PowerPC. Это то, что у меня есть на данный момент:

 function exts(value, from, to) {
    return (value | something_goes_here);
}
  

value это целочисленный ввод, from это количество битов, которое value используется, и to это целевая длина бита.

Какой наиболее эффективный способ создать число, для которого to - from биты установлены равными 1 , за которыми следуют from биты, установленные равными 0 ?

Игнорируя тот факт, что в JavaScript нет 0b синтаксиса чисел, например, если я вызвал

 exts(0b1010101010, 10, 14)
  

Я бы хотел, чтобы функция ИЛИ значение с 0b11110000000000 , возвращающее результат со знаком расширения 0b11111010101010 .

Комментарии:

1. В JS нет целочисленного типа, только числа с плавающей запятой. Возможно, вы захотите использовать типизированные массивы, но для этого потребуются современные браузеры. В любом случае, в C обычно вы бы сделали это, выполнив (value|((-1)<<number_of_trailing_zeros))

Ответ №1:

Число, содержащее p один бит, за которым следуют q нулевые биты, может быть сгенерировано с помощью

 ((1<<p)-1)<<q
  

таким образом, в вашем случае

 ((1<<(to-from))-1)<<from
  

или намного короче

 (1<<to)-(1<<from)
  

Ответ №2:

если у вас есть число 2 ^ q (= 1, сдвинутое влево на q), представленное в виде целого числа шириной p q бит, оно имеет представление:

 0...010...0
 p-1    q
  

тогда 2 ^ q — 1 имеет представление

 0...01...1
  p    q
  

что является полной противоположностью того, что вы хотите. Итак, просто переверните биты

следовательно, то, что вы хотите, не ((1 СДВИГ ВЛЕВО на q) — 1) = ~((1 << q) - 1) в нотации c.

Комментарии:

1. Но если я расширяю число до чего-то меньшего, чем 32 бита, что является единственной доступной «целочисленной» шириной в JavaScript (т. Е. (p q) < 32 ), то, насколько я могу судить, ваш метод приведет к тому, что старшие 32 - (p q) биты будут установлены на 1 , что ошибочно.

2. я предполагал, что вы используете тип правильной ширины. вы могли бы И что у меня там было с ((1 << to) — 1), чтобы отменить установку старших битов

3. А, я понимаю, что ты имеешь в виду. Спасибо!

Ответ №3:

Я не слишком хорошо знаком с двоичной математикой в JavaScript… Но если вам нужно ИЛИ число с 0b11110000000000 , то, я полагаю, вы бы просто преобразовали это в десятичное число (что дало бы вам 15360 ), и сделали value | 15360 .

Соответствующая информация, которая может оказаться полезной: parseInt("11110000000000", 2) преобразует двоичное число (указанное в виде строки) в десятичное число и (15360).toString(2) преобразует десятичное число (в данном случае 15360) в двоичное число (результатом является строка).


Пересмотренное решение

Вероятно, есть более элегантный и математический метод, но вот быстрое и грязное решение:

 var S = "";
for(var i=0;i<p;i  )
   S  = "1";
for(i=0;i<q;i  )
   S  = "0";
S = parseInt(S, 2); // convert to decimal
  

Комментарии:

1. Это был только пример. Я хотел бы знать, как эффективно создать число, состоящее из p битов, установленных в 1 , за которыми следуют q биты, установленные в 0 .