Какой вариант лучше использовать для деления целого числа на 2?

406

Какой из следующих методов является лучшим вариантом для деления целого числа на 2 и почему?

Техника 1:

x = x >> 1;

Техника 2:

x = x / 2;

Вот xцелое число.

Абхинит
источник
75
Если вы действительно хотите присвоить результат xснова, ни один из них не подходит таким образом: он должен быть либо, x >>= 1либо в x /= 2зависимости от того, что вы намерены выразить с помощью операции. Не потому, что это быстрее (любой современный компилятор все равно скомпилирует все эквивалентные варианты в одинаковую, быструю сборку), а потому, что это менее запутанно.
оставил около
33
Я не согласен с левой стороны. - Но я думаю, что стоит отметить, что во многих языках программирования есть операция, называемая арифметическим сдвигом, которая сохраняет бит знака на месте и, следовательно, работает со знаковыми значениями, как и ожидалось. Синтаксис может быть как x = x >>> 1. Также обратите внимание, что в зависимости от платформы и компилятора может быть разумно вручную оптимизировать деления и умножения, используя сдвиги. - Думая о микроконтроллерах, например, без прямой поддержки ALU для умножения.
JimmyB
36
Я предпочитаю, x /= 2потому что x >>= 1выглядит слишком похоже на монадное связывание;)
fredoverflow
19
@leftaroundabout - Я просто считаю , что гораздо более удобным для чтения , чтобы писать x = x / 2вместо x /= 2. Субъективное предпочтение может быть :)
JimmyB
8
@HannoBinder: безусловно, субъективный, в частности, много привычки. ИМО, на языке, где все арифметические операторы имеют ⬜=комбинации, их следует использовать, когда это возможно. Он устраняет шум и акцентирует внимание на том факте, что xон изменен , в то время как общий =оператор скорее предполагает, что он принимает совершенно новое значение, независимое от старого. - Всегда избегать комбинированных операторов (так что это читаемое так , кто знает только математические оператор) может иметь свою точку , а также, но тогда вы должны были бы отказаться от крайне полезных ++, --, +=тоже.
оставил около

Ответы:

847

Используйте операцию, которая лучше всего описывает то, что вы пытаетесь сделать.

  • Если вы рассматриваете число как последовательность битов, используйте битное смещение.
  • Если вы рассматриваете это как числовое значение, используйте деление.

Обратите внимание, что они не совсем эквивалентны. Они могут давать разные результаты для отрицательных целых чисел. Например:

-5 / 2  = -2
-5 >> 1 = -3

(Ideone)

Марк Байерс
источник
20
Первоначальный вопрос был также неопределенным в отношении термина «лучший». «Лучший» с точки зрения скорости, читабельности, экзаменационных вопросов, чтобы обмануть студентов и т. Д. ... В отсутствие объяснения того, что означает «лучший», это кажется наиболее правильным ответом.
Рэй
47
В C ++ 03 оба являются реализацией, определенной для отрицательных чисел, и могут давать одинаковые результаты. В C ++ 11 деление хорошо определено для отрицательных чисел, но сдвиг все еще определяется реализацией.
Джеймс Канз
2
В то время как определение / является реализацией (если округляется в большую или меньшую сторону для отрицательных чисел), определено в ранних стандартах C. Он всегда должен соответствовать% (оператор по модулю / остатку).
Ctrl-Alt-Delor
7
«Определенная реализация» означает, что разработчик компилятора может выбирать из нескольких вариантов реализации, обычно с существенными ограничениями. Здесь, одно ограничение является то , что %и /операторы должны быть согласованы для положительных и отрицательных операндов так , что (a/b)*b+(a%b)==aсправедливо независимо от признаков aи b. Обычно автор делает выбор, который позволяет добиться максимальной производительности процессора.
RBerteig
6
Так что каждый, кто говорит, что «компилятор все равно конвертирует его», неправ, не так ли? Если компилятор не может гарантировать, что вы имеете дело с неотрицательным целым числом (либо это константа, либо целое число без знака), он не может изменить его на сдвиг
Кип
225

Первый выглядит как деление? Нет. Если вы хотите разделить, используйте x / 2. Компилятор может оптимизировать его для использования битового сдвига, если это возможно (это называется снижением прочности), что делает его бесполезной микрооптимизацией, если вы делаете это самостоятельно.

Cat Plus Plus
источник
15
Многие компиляторы не превратят деление на степень двух в битовое смещение. Это было бы неправильной оптимизацией для целых чисел со знаком. Вы должны попытаться посмотреть на результаты сборки вашего компилятора и убедиться в этом сами.
exDM69
1
IIRC Я использовал это для ускорения параллельного сокращения в CUDA (избегайте целочисленного div). Однако это было больше года назад, и мне интересно, насколько умны компиляторы CUDA в наши дни.
Нильс
9
@ exDM69: Многие компиляторы делают это даже для целых чисел со знаком и просто настраивают их в соответствии со знаками. Хороший инструмент для игры с этими вещами
таков
19
@ exDM69: И это актуально, как? Я сказал «если возможно», а не «всегда». Если оптимизация неверна, то выполнение ее вручную не делает ее правильной (плюс, как уже упоминалось, GCC достаточно умен, чтобы найти правильную замену для целых чисел со знаком).
Cat Plus Plus
4
Глядя на страницу WikiPedia, это кажется спорным, но я бы не назвал это снижением силы. Снижение прочности - это когда в цикле вы уменьшаете, например, умножение до сложения путем добавления к предыдущим значениям в цикле. Это скорее оптимизация глазка, которую компиляторы могут делать довольно надежно.
SomeCallMeTim
189

Скопировать: есть так много причин, чтобы использовать x = x / 2; Вот некоторые из них:

  • он выражает ваше намерение более четко (при условии, что вы не имеете дело с битами регистра сдвоенного твида или чем-то еще)

  • компилятор все равно сведет это к операции сдвига

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

  • если деление будет частью более крупного выражения, вы с большей вероятностью получите правильный приоритет, если будете использовать оператор деления:

    x = x / 2 + 5;
    x = x >> 1 + 5;  // not the same as above
  • арифметика со знаком может усложнить ситуацию даже больше, чем проблема старшинства, упомянутая выше

  • повторить - компилятор уже сделает это за вас в любом случае. Фактически, он преобразует деление на константу в серию сдвигов, добавлений и умножений для всех видов чисел, а не только для степеней двух. Смотрите этот вопрос для ссылки на еще больше информации об этом.

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

Майкл Берр
источник
5
Стоит также добавить, что хотя существуют правила приоритета, нет ничего плохого в использовании скобок. Перерабатывая некоторый производственный код, я на самом деле увидел нечто вроде формы a/b/c*d(где a..dобозначены числовые переменные) вместо гораздо более читабельного (a*d)/(b*c).
1
Производительность и оптимизация зависят от компилятора и цели. Например, я выполняю некоторую работу для микроконтроллера, где отключено что-либо выше, чем -O0, если вы не купите коммерческий компилятор, поэтому компилятор определенно не превратится в деление битов. Кроме того, битовые сдвиги занимают один цикл, а деление занимает 18 циклов на этой цели, и, поскольку тактовая частота микроконтроллеров довольно низкая, это может быть действительно заметным ударом по производительности (но это зависит от вашего кода - вы обязательно должны использовать /, пока профилирование не скажет вам это проблема!)
4
@JackManey, если есть вероятность того, что a*dили b*cпроизойдет переполнение, менее читаемая форма не эквивалентна и имеет очевидное преимущество. PS Я согласен, что скобки - твой лучший друг.
Марк Рэнсом
@MarkRansom - Справедливое замечание (даже если я столкнулся a/b/c*dс кодом R - в контексте, где переполнение означало бы, что с данными что-то серьезно не так, а не, скажем, в критичном для производительности блоке кода C).
Код x=x/2;только «более понятен», чем x>>=1если бы xон никогда не был нечетным отрицательным числом, или не заботятся об ошибках. В противном случае x=x/2;и x>>=1;имеют разные значения. Если нужно вычислить значение x>>=1, я бы посчитал это более понятным, чем x = (x & ~1)/2или x = (x < 0) ? (x-1)/2 : x/2, или любую другую формулировку, которую я могу придумать, используя деление на два. Точно так же, если нужно вычислить значение x/=2, это будет яснее, чем ((x + ((unsigned)x>>31)>>1).
суперкат
62

Какой вариант является лучшим и почему для деления целого числа на 2?

Зависит от того, что вы подразумеваете под лучшим .

Если вы хотите, чтобы ваши коллеги ненавидели вас или сделали ваш код трудным для чтения, я бы определенно выбрал первый вариант.

Если вы хотите разделить число на 2, переходите ко второму.

Два не эквивалентны, они не ведут себя одинаково, если число отрицательное или внутри больших выражений - битное смещение имеет меньший приоритет, чем +или -, деление имеет более высокий приоритет.

Вы должны написать свой код, чтобы выразить его намерения. Если вам важна производительность, оптимизатор хорошо справляется с подобной микрооптимизацией.

Лучиан Григоре
источник
58

Просто используйте разделяемую ( /), предполагая, что это понятнее. Компилятор будет оптимизировать соответственно.

джастин
источник
34
Компилятор должен оптимизировать соответственно.
Noctis Skytower
12
Если компилятор не оптимизирует соответственно, вы должны использовать лучший компилятор.
Дэвид Стоун
3
@DavidStone: На каких процессорах компилятор может оптимизировать деление потенциально отрицательного целого числа со знаком на любую константу, отличную от 1, чтобы быть столь же эффективным, как сдвиг?
суперкат
1
@supercat: Это хороший момент. Конечно, вы могли бы хранить значение в целом числе без знака (которое, как мне кажется, имеет гораздо худшую репутацию, чем при сочетании с предупреждениями о несоответствии со знаком / без знака), и большинство компиляторов также имеют способ сказать им, что что-то верно при оптимизации , Я бы предпочел обернуть это в макрос совместимости и иметь что-то вроде ASSUME(x >= 0); x /= 2;over x >>= 1;, но это все еще важный момент для обсуждения.
Дэвид Стоун
39

Я согласен с другими ответами, которые вы должны одобрить, x / 2потому что его цель более ясна, и компилятор должен оптимизировать его для вас.

Тем не менее, еще одна причина предпочесть x / 2более x >> 1, что поведение >>зависит от реализации , если xэто знаковоеint и отрицательный.

Из раздела 6.5.7, пул 5 стандарта ISO C99:

Результат E1 >> E2- E1сдвинутые вправо E2битовые позиции. Если E1имеет тип без знака или E1имеет тип со знаком и неотрицательное значение, значение результата является неотъемлемой частью отношения E1/ 2 E2. Если E1имеет тип со знаком и отрицательное значение, результирующее значение определяется реализацией.

jamesdlin
источник
3
Стоит отметить, что поведение, которое многие реализации определяют для x>>scalepowerотрицательных чисел, будет именно тем, что необходимо при делении значения на степень два для таких целей, как рендеринг экрана, при этом использование x/scalefactorбудет неправильным, если не применить поправки к отрицательным значениям.
суперкат
32

x / 2понятнее и x >> 1не намного быстрее (согласно микропроцессору, примерно на 30% быстрее для Java JVM). Как уже отмечали другие, для отрицательных чисел округление немного отличается, поэтому вы должны учитывать это, когда хотите обработать отрицательные числа. Некоторые компиляторы могут автоматически конвертировать x / 2в, x >> 1если они знают, что число не может быть отрицательным (даже подумал, что я не смог это проверить).

Даже x / 2 может не использовать (медленно) инструкцию процессора деления, потому что некоторые сочетания клавиш возможны , но это все же медленнее, чемx >> 1 .

(Это C / C ++ вопрос, другие языки программирования имеют больше операторов. Для Java есть также сдвиг вправо без знака, x >>> 1, что опять - таки отличается. Это позволяет правильно рассчитать среднее (среднее) значение из двух значений, так что (a + b) >>> 1волей возвращает среднее значение даже для очень больших значений aи b. Это требуется, например, для двоичного поиска, если индексы массива могут стать очень большими. Во многих версиях двоичного поиска была ошибка , поскольку они использовали (a + b) / 2для вычисления среднего. не работает правильно. Правильное решение использовать (a + b) >>> 1вместо.)

Томас Мюллер
источник
1
Составители не может конвертировать x/2в x>>1в тех случаях , когда xможет быть отрицательным. Если то x>>1, что нужно, это значение, которое будет вычислено, это почти наверняка будет быстрее, чем любое выражение, x/2которое вычисляет то же значение.
суперкат
Вы правы. А компилятор может преобразовать только x/2в x>>1если он знает , что значение не является отрицательным. Я постараюсь обновить свой ответ.
Томас Мюллер
тем не менее, компиляторы по-прежнему избегают divинструкции путем преобразования x/2в (x + (x<0?1:0)) >> 1(где >> - арифметическое смещение вправо, которое сдвигается в знаковых битах). Для этого нужно 4 инструкции: скопировать значение, shr (чтобы получить только знаковый бит в регистре), добавить, sar. goo.gl/4F8Ms4
Питер Кордес
Вопрос помечен как C и C ++.
Джош Сэнфорд
22

Кнут сказал:

Преждевременная оптимизация - корень всего зла.

Поэтому я предлагаю использовать x /= 2;

Таким образом, код легко понять, и я думаю, что оптимизация этой операции в такой форме не означает большой разницы для процессора.

Иван Калифорниас
источник
4
Что бы вы посчитали предпочтительным методом уменьшения числа на степень два, если хотите, чтобы целые числа поддерживали аксиому (которая применима к натуральным числам и действительным числам), которая (n + d) / d = (n / d) + 1? Нарушения этой аксиомы при масштабировании графики приведут к видимым «швам» в результате. Если кто-то хочет что-то равномерное и почти симметричное относительно нуля, это (n+8)>>4прекрасно работает. Можете ли вы предложить какой-либо подход, который был бы столь же ясным или эффективным без использования подписанного сдвига вправо?
суперкат
19

Посмотрите на вывод компилятора, чтобы помочь вам принять решение. Я запустил этот тест на x86-64 с
gcc (GCC) 4.2.1 20070719 [FreeBSD]

Также смотрите результаты компиляции онлайн на godbolt .

То, что вы видите, это то, что компилятор использует sarl(арифметическое смещение вправо) инструкцию в обоих случаях, поэтому он распознает сходство между двумя выражениями. Если вы используете деление, компилятор также должен скорректировать отрицательные числа. Для этого он сдвигает знаковый бит до младшего разряда и добавляет его к результату. Это устраняет проблему смещений на единицу при смещении отрицательных чисел по сравнению с тем, что будет делать деление.
Поскольку в случае деления выполняется 2 смены, а в явном случае смен - только одна, мы теперь можем объяснить некоторые различия в производительности, измеренные другими ответами.

C-код с выводом сборки:

Для деления ваш вклад будет

int div2signed(int a) {
  return a / 2;
}

и это компилируется в

    movl    %edi, %eax
    shrl    $31, %eax
    addl    %edi, %eax
    sarl    %eax
    ret

аналогично для смены

int shr2signed(int a) {
  return a >> 1;
}

с выходом:

    sarl    %edi
    movl    %edi, %eax
    ret
Майкл Донохью
источник
В зависимости от того, что вы делаете, это может исправить ошибку «один за другим», или это может вызвать ошибку «один за другим» (по сравнению с тем, что действительно необходимо), что потребует использования дополнительного кода для ее исправления. Если то, что кто-то хочет, является неудачным результатом, сдвиг вправо быстрее и проще, чем любая другая альтернатива, о которой я знаю.
суперкат
Если вам нужен пол, вряд ли вы бы описали то, что вы хотите, как «деление на 2»
Майкл Донохью
Деление натуральных чисел и действительных чисел подтверждает аксиому, что (n + d) / d = (n / d) +1. Деление действительных чисел также поддерживает (-n) / d = - (n / d), аксиому, которая бессмысленна с натуральными числами. Невозможно иметь оператор деления, который замкнут на целых числах и поддерживает обе аксиомы. На мой взгляд, говорить, что первая аксиома должна выполняться для всех чисел, а вторая только для действительных, кажется более естественным, чем говорить, что первая должна выполняться для целых чисел или вещественных чисел, но не для целых чисел. Далее, мне любопытно, в каких случаях вторая аксиома действительно полезна .
суперкат
1
Метод целочисленного деления, который удовлетворяет первой аксиоме, разделит числовую линию на области размера d. Такое разбиение полезно для многих целей. Даже если вы бы предпочли иметь точку останова где-то, отличную от 0 до -1, добавление смещения переместит ее. Целочисленное деление, которое удовлетворяет второй аксиоме, разделит числовую линию на области, которые в основном имеют размер d, но одна из которых имеет размер 2*d-1. Не совсем "равные" подразделения. Можете ли вы предложить предложения о том, когда раздел чудаков на самом деле полезен?
Суперкат
Ваш вывод компилятора для shr2signed неверен. gcc на x86 решает реализовать >> целых чисел со знаком с арифметическими сдвигами ( sar). goo.gl/KRgIkb . Этот пост списка рассылки ( gcc.gnu.org/ml/gcc/2000-04/msg00152.html ) подтверждает, что gcc исторически использует арифметические сдвиги для подписанных целых, поэтому маловероятно, что FreeBSD gcc 4.2.1 использовала беззнаковое смещение. Я обновил ваш пост, чтобы исправить это, и в начале параграфа говорилось, что оба использовали shr, когда они фактически используют SAR. SHR - это то, как он извлекает знаковый бит для /случая. Также включена ссылка Godbolt.
Питер Кордес
15

Просто добавленная заметка -

x * = 0.5 часто будет быстрее в некоторых языках на основе виртуальных машин - особенно в ActionScript, так как переменную не нужно проверять на деление на 0.

ansiart
источник
2
@minitech: Это такой плохой тест. Весь код в тесте является постоянным. Прежде чем код будет даже JITed, он удалит все константы.
@ M28: Я был почти уверен, что внутренности jsPerf (то есть eval) сделали это каждый раз заново. В любом случае, да, это довольно плохой тест, потому что это очень глупая оптимизация.
Ry-
13

Используйте x = x / 2; ИЛИ x /= 2;Потому что возможно, что новый программист будет работать над этим в будущем. Так что ему будет легче узнать, что происходит в строке кода. Каждый может не знать о такой оптимизации.

Имдад
источник
12

Я говорю для целей соревнований по программированию. Как правило, они имеют очень большие входные данные, где деление на 2 происходит много раз, и известно, что входные данные являются положительными или отрицательными.

х >> 1 будет лучше, чем х / 2. Я проверил на ideone.com, запустив программу, в которой было выполнено более 10 ^ 10 делений на 2 операции. Для x / 2 потребовалось около 5,5 с, тогда как для х >> 1 потребовалось около 2,6 с для той же программы.

Шашват Кумар
источник
1
Для значений без знака компилятор должен оптимизировать x/2до x>>1. Для значений со знаком почти все реализации определяют x>>1значение, которое эквивалентно, x/2но может быть вычислено быстрее, когда xположительно, и полезно отличается от того, x/2когда xотрицательно.
суперкат
12

Я бы сказал, что есть несколько вещей, которые следует учитывать.

  1. Сдвиг битов должен быть быстрее, поскольку для сдвига битов действительно не требуется специальных вычислений, однако, как указывалось, существуют потенциальные проблемы с отрицательными числами. Если вы уверены, что у вас положительные числа, и вы ищете скорость, я бы порекомендовал bithift.

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

  3. В зависимости от используемого оборудования операции могут иметь разную скорость. Закон Амдала состоит в том, чтобы ускорить общее дело. Таким образом, у вас может быть оборудование, которое может выполнять различные операции быстрее, чем другие. Например, умножение на 0,5 может быть быстрее, чем деление на 2. (Конечно, вам может понадобиться взять слово умножения, если вы хотите применить целочисленное деление).

Если вам нужна чистая производительность, я бы порекомендовал создать несколько тестов, которые могли бы выполнять операции миллионы раз. Попробуйте выполнить несколько раз (ваш размер выборки), чтобы определить, какой из них является статистически наилучшим для вашей ОС / Аппаратное обеспечение / Компилятор / Код.

Джеймс Оравец
источник
2
«Bitshift должен быть быстрее». компиляторы оптимизируют деление на битовые сдвиги
Тревор Хикки
Я надеюсь, что они будут, но если у вас нет доступа к источнику компилятора, вы не можете быть уверены :)
Джеймс Оравец
1
Я бы также порекомендовал bithift, если его реализация обрабатывает его наиболее распространенным способом, и способ, которым кто-то хочет обрабатывать отрицательные числа, соответствует тому, что >>делает, а не тому, что /делает.
суперкат
12

Что касается процессора, операции сдвига битов выполняются быстрее, чем операции деления. Тем не менее, компилятор знает это и будет соответствующим образом оптимизировать, насколько это возможно, так что вы можете писать код так, как вам удобно, и быть спокойным, зная, что ваш код работает эффективно. Но помните, что unsigned intможет (в некоторых случаях) быть оптимизирован лучше, чем intпо причинам, указанным ранее. Если вам не нужна арифметика со знаком, то не включайте бит знака.

tylerl
источник
11

х = х / 2; это подходящий код для использования ... но работа зависит от вашей собственной программы, как вывод, который вы хотели произвести.

Gooner
источник
11

Сделайте ваши намерения более понятными ... например, если вы хотите разделить, используйте x / 2 и позвольте компилятору оптимизировать его для оператора сдвига (или чего-либо еще).

Современные процессоры не позволят этим оптимизациям повлиять на производительность ваших программ.

Атул Кумар
источник
10

Ответ на этот вопрос будет зависеть от среды, в которой вы работаете.

  • Если вы работаете с 8-битным микроконтроллером или чем-то еще без аппаратной поддержки умножения, сдвиг битов является обычным делом, и хотя компилятор почти наверняка превратится x /= 2в x >>= 1, присутствие символа деления вызовет больше удивлений в этой среде, чем используя сдвиг, чтобы произвести разделение.
  • Если вы работаете в критичной к производительности среде или разделе кода, или ваш код может быть скомпилирован с отключенной оптимизацией компилятора, x >>= 1 комментарий с пояснением его аргументации, вероятно, лучше всего использовать для ясности цели.
  • Если вы не выполняете одно из указанных выше условий, сделайте свой код более читабельным, просто используя x /= 2. Лучше сэкономить следующему программисту, который смотрит на ваш код, 10-секундную двойную проверку вашей смены, чем без необходимости доказывать, что вы знали, что сдвиг был более эффективным без оптимизации компилятора.

Все они предполагают целые числа без знака. Простой переход, вероятно, не то, что вы хотите подписать. Кроме того, DanielH хорошо описывает использование x *= 0.5некоторых языков, таких как ActionScript.

gkimsey
источник
8

мод 2, тест для = 1. не знаю синтаксис в с. но это может быть самым быстрым.

circusdei
источник
7

В целом правильное смещение делит:

q = i >> n; is the same as: q = i / 2**n;

иногда это используется для ускорения программ за счет ясности. Я не думаю, что вы должны это делать. Компилятор достаточно умен, чтобы выполнить ускорение автоматически. Это означает, что внесение смены ничего не даст вам за счет ясности .

Взгляните на эту страницу из Практического программирования на C ++.

Моуна Шейхна
источник
Если кто-то хочет вычислить значение, которое, например (x+128)>>8, вычислило бы значения, xне близкие к максимальному, как можно было бы сделать это кратко без сдвига? Обратите внимание, что (x+128)/256это не сработает. Вы знаете какое-нибудь хорошее выражение, которое будет?
суперкат
7

Очевидно, что если вы пишете свой код для следующего парня, который его читает, перейдите к ясности "x / 2".

Однако, если ваша цель - скорость, попробуйте оба способа и время результаты.Несколько месяцев назад я работал над процедурой свертки растровых изображений, которая включала пошаговое выполнение массива целых чисел и деление каждого элемента на 2. Я сделал все, чтобы оптимизировать его, включая старый трюк с заменой «x >> 1» на «x». / 2" .

Когда я на самом деле рассчитал оба пути, я с удивлением обнаружил, что x / 2 был быстрее, чем x >> 1

Это было с использованием Microsoft VS2008 C ++ с включенными оптимизациями по умолчанию.

Крис Беннет
источник
4

С точки зрения производительности. Операции сдвига процессора выполняются значительно быстрее, чем деление кодов операций. Таким образом, деление на два или умножение на 2 и т. Д. Приносит пользу от сменных операций.

Что касается внешнего вида. Как инженеры, когда мы стали настолько привязаны к косметике, что даже красавицы не пользуются! :)

Farjad
источник
3

X / Y - правильный оператор смещения ... и ">>". Если мы хотим разделить целое число на два, мы можем использовать оператор деления (/). оператор сдвига используется для сдвига битов.

х = х / 2; х / = 2; мы можем использовать как это ..

шоколадный мальчик
источник
0

Хотя x >> 1 быстрее, чем x / 2, правильное использование >> при работе с отрицательными значениями немного сложнее. Это требует чего-то похожего на следующее:

// Extension Method
public static class Global {
    public static int ShiftDivBy2(this int x) {
        return (x < 0 ? x + 1 : x) >> 1;
    }
}
Дарин
источник