Что значит >> и 0xfffffff8? - PullRequest
       2

Что значит >> и 0xfffffff8?

6 голосов
/ 11 октября 2011

Мне сказали, что (i >> 3) is faster than (i/8), но я не могу найти информацию о том, что такое >>.Может кто-нибудь указать мне ссылку, которая объясняет это?

Тот же человек сказал мне: "int k = i/8, за которым следует k*8, лучше выполнить (i&0xfffffff8);", но опять же Google не помог м ...

Спасибо за любые ссылки!

Ответы [ 11 ]

9 голосов
/ 11 октября 2011

Как объяснено здесь оператор >> - это просто побитовое смещение битов i. Таким образом, сдвиг i 1 бита вправо приводит к целочисленному делению на 2, а сдвиг на 3 бита приводит к делению на 2 ^ 3 = 8.

Но в настоящее время эту оптимизацию для деления на степени два больше не следует делать, поскольку компиляторы должны быть достаточно умными, чтобы делать это сами.

Аналогично, побитовое И с 0xFFFFFFF8 (1 ... 1000, последние 3 бита 0) равно округлению i до ближайшего кратного 8 (как это делает (i/8)*8), поскольку оно обнуляет последние 3 бита i.

2 голосов
/ 11 октября 2011

int x = i / 8 * 8:

1) i / 8, можно заменить на i >> 3 - сдвиг по битам вправо до 3 цифр (8 = 2 ^ 3)

2) Сравнение i & xfffffff8 с маской. Например, у вас есть:

i = 11111111
k (i/8) would be: 00011111  
x (k * 8) would be: 11111000

Поэтому операция просто сбрасывает последние 3 бита: и сопоставимые операции умножения и деления затрат времени можно переписать просто с помощью

i & xfffffff8 - сравнение с (... маска 11111000)

2 голосов
/ 11 октября 2011

Битовый сдвиг вправо.i >> 3 сдвигает i целое число на 3 места вправо [двоичный код] - иначе делим на 2^3.

1 голос
/ 11 октября 2011

Битовое смещение.

Предположим, у меня есть 8-разрядное целое число, в двоичном виде

01000000

Если я оставил сдвиг (>> оператор) 1 в результате получается

00100000

Если я затем сдвинусь вправо (<< оператор) 1, я четко вернусь к износу, я начал </p>

01000000

Оказывается, поскольку первое двоичное целое число равноэквивалентно

0 * 2 ^ 7 + 1 * 2 ^ 6 + 0 * 2 ^5 + 0 * 2 ^ 4 + 0 * 2 ^ 3 + 1 * 2 ^ 2 + 0 * 2 ^ 1 + 0 * 2 ^ 0

или просто 2 ^ 6 или 64

Когда мы сместим вправо к сдвигу 1, мы получим следующее

0 * 2 ^ 7 + 0 * 2 ^ 6 + 1 * 2 ^ 5 + 0 * 2 ^ 4 + 0 * 2 ^ 3+ 1 * 2 ^ 2 + 0 * 2 ^ 1 + 0 * 2 ^ 0

или просто 2 ^ 5 или 32

Что означает

i >> 1 

то же самое, что и

i / 2

Если мы сдвинемся еще раз (i >> 2), мы снова разделим на 2 и получим

i / 2 / 2

Что на самом деле

i / 4

Не совсем математическое доказательство, но вы можете видеть, что справедливо следующее

i >> n == i / (2^n)
1 голос
/ 11 октября 2011

Оператор >> является оператором сдвига битов. Он берет бит, представленный значением, и сдвигает их на заданное количество слотов вправо.

1 голос
/ 11 октября 2011
1 голос
/ 11 октября 2011

Относительно первой половины:

>> - битовый сдвиг вправо.

Таким образом, сдвиг числового значения на 3 бита вправо аналогичен делению на 8и int получение результата.

Вот хороший справочник по операторам и их приоритетам: http://web.cs.mun.ca/~michael/c/op.html

Вторая часть вашего вопроса касается оператора &, который немногоиПримером является ANDing i и число, которое оставляет все установленные биты, кроме 3 младших значащих.По сути, это то же самое, что происходит, когда у вас есть число, разделите его на 8, сохраните результат как целое число, а затем умножьте этот результат на 8.

Причина в том, что деление на 8 и сохранениецелое число - это то же самое, что и смещение бит в три позиции вправо, а умножение на 8 и сохранение результата в целое число аналогично смещению бит в 3 места влево.

Итак, если выумножаете или делите на степень 2, например, на 8, и вы согласитесь с усечением битов, которое происходит, когда вы сохраняете результат, в результате которого int, сдвиг битов происходит быстрее, оперативнее.Это потому, что процессор может пропустить алгоритм умножения / деления и просто перейти к сдвигу битов, который включает в себя несколько шагов.

0 голосов
/ 11 октября 2011

>> смещает число вправо. Рассмотрим двоичное число 0001000, которое представляет 8 в десятичной записи. Если сдвинуть его на 3 бита вправо, получится 0000001, то есть число 1 в десятичной записи. Таким образом, вы видите, что каждое 1-битное смещение вправо фактически является делением на 2. Обратите внимание, что оператор обрезает часть результата с плавающей точкой. Следовательно, i >> n подразумевает i/2^n. Это может быть быстро в зависимости от реализации компилятора. Но это обычно происходит прямо в регистрах и поэтому очень быстро по сравнению с традиционным делением и умножением.

Ответ на вторую часть содержится в самой первой. Поскольку при делении также обрезается вся часть результата с плавающей запятой, деление на 8 теоретически сдвинет ваше число 3 битов вправо, что приведет к потере всей информации о самых правых 3 битах. Теперь, когда вы снова умножаете его на 8 (что в теории означает смещение влево на 3 бита), вы добавляете самые правые 3 биты в ноль после смещения результата влево на 3 бита. Следовательно, завершенная операция может рассматриваться как одна операция «&» с 0xfffffff8, что означает, что число имеет все биты 1, за исключением самых правых 4 битов, которые равны 1000.

0 голосов
/ 11 октября 2011

Это называется сдвигом битов, это операция над битами, например, если у вас есть число на двоичной основе, скажем, 8, это будет 1000, поэтому

x = 1000;
y = x >> 1; //y = 100 = 4
z = x >> 3; //z = 1 
0 голосов
/ 11 октября 2011

Ваше смещение битов в двоичном формате, например:

1000 == 8

0100 == 4 (>> 1)

0010 == 2 (>> 2)

0001 == 1 (>> 3)

Поскольку вы используете систему с основанием два, вы можете воспользоваться некоторыми делителями (только целыми числами!) И просто битом-сдвиг.Кроме того, я полагаю, что большинство компиляторов знают это и сделают это для вас.

Что касается второй части:

(i & 0xfffffff8);

Скажите, что я = 16

0x00000010 & 0xfffffff8 == 16

(16/8) * 8 == 16

Снова используя логические операторы двоичного кода.Изучите, как логические операторы работают с двоичным кодом, чтобы действительно ясно понять, что происходит на битовом уровне (и как читать шестнадцатеричный код).

...