#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
.