@Neil - Modulo и Binary И это довольно фундаментальные операции, я предполагаю, что они примерно одинаковы на любом компьютерном языке.
Джеймс Колпак,
1
Я действительно немного устал от того, что не вижу опубликованного языка :) Хотя обычно я предполагаю, что если они не указывают, я предполагаю, что это означает C ++ или C. Интересно, насколько это правда ...
Гарет Клаборн
1
Просто для тех, кто изо всех сил пытается понять это, взгляните на stackoverflow.com/a/13784820/1414639 . Да, и в JS с V8 я получаю очень небольшой прирост производительности за счет использования побитовых операторов.
Барди Харбороу,
1
@JamesKolpack Поразрядная операция может выполняться на ЦП НАМНОГО быстрее, чем по модулю. Фактически, распространенный трюк сборки для обнуления регистра заключается в выполнении XOR с самим собой (из-за этого факта). В настоящее время компилятор может оптимизировать по модулю степени двойки, но я не знаю,
Кайзер Кейстер
Ответы:
70
Во-первых, сказать, что
x % 2 == x & 1
Простой контрпример: x = -1. Во многих языках, в том числе Java, -1 % 2 == -1. То есть, %это не обязательно традиционное математическое определение по модулю. Java, например, называет это «оператором остатка».
Что касается побитовой оптимизации, в поразрядной арифметике «легко» можно выполнить только степень двойки по модулю. Вообще говоря, только по модулю степеней основания b "легко" можно сделать с представлением чисел с основанием b .
В основании 10, например, для неотрицательного N, N mod 10^kпросто принимая значащие kцифры.
@BlueRaja: если вы разрешаете отрицательные числа, то, в основном, вы можете быть уверены (особенно потому, что язык не упоминается), так это то (a / b) / b + a % b == a, что для операторов C-типа целые числа a и b, b ненулевые, а также abs(a % b) < abs(b)с теми же условиями.
Дэвид Торнли
1
@DavidThornley - предположим, вы имеете в виду (a / b)* b + a % b == a.
sfjac
40
Есть только простой способ найти числа по модулю 2 ^ i с помощью побитового вычисления.
Существует изобретательный способ решения случаев Мерсенна по ссылке, например n% 3, n% 7 ... Существуют особые случаи для n% 5, n% 255 и составные случаи, такие как n% 6.
Для случаев 2 ^ i, (2, 4, 8, 16 ...)
n % 2^i = n & (2^i - 1)
Более сложные объяснить сложно. Читайте, только если вам очень любопытно.
голос ++; Отличная ссылка, спасибо за ссылку. Советую другим взглянуть, это стоит прочитать, даже если это немного сложно.
varzeak
ссылка - лучшая часть ответа.
Амит Кумар
n% 2 ^ i = n & (1 << i - 1)
Картик Сингх
18
Это работает только для степеней двойки (и часто только положительных), потому что они обладают уникальным свойством иметь только один бит, установленный на «1» в их двоичном представлении. Поскольку ни один другой класс чисел не обладает этим свойством, вы не можете создавать побитовые выражения и для большинства выражений модуля.
Кроме того, зачем вам делить, если вы не хотите использовать по модулю? AFAIK, инструкция по делению такая же, как и для получения остатка.
Horse SMith
2
@SriramMurali Это потому, что вы использовали четный мод, конечно, он не сработает, это обходной путь для нечетного, как сказал OP.
ylun.ca
3
Без использования побитового &оператора и ( ) в двоичном формате нет. Эскиз доказательства:
Предположим, что существует такое значение k , что x & k == x % (k + 1), но k! = 2 ^ n - 1 . Тогда, если x == k , выражение x & kкажется «работает правильно», и результат будет k . Теперь рассмотрим х == ки : если были какие -то «0» биты к , есть некоторые я больше 0 , которые ки могут быть выражены только с 1-бит в этих положениях. (Например, 1011 (11) должно стать 0111 (7), когда из него было вычтено 100 (4), в этом случае бит 000 становится 100, когда i = 4. ) Если бит из выражения k должен измениться с нуля одному, чтобы представить ки, то он не может правильно вычислить x% (k + 1) , которое в этом случае должно быть ki , но нет возможности для побитового логического значения и создания этого значения с учетом маски.
Используя bitwise_and, bitwise_or и bitwise_not, вы можете изменять любые битовые конфигурации на другие битовые конфигурации (т. Е. Этот набор операторов является «функционально полным»). Однако для таких операций, как модуль, общая формула обязательно будет довольно сложной, я бы даже не стал пытаться ее воссоздать.
Ответы:
Во-первых, сказать, что
Простой контрпример:
x = -1
. Во многих языках, в том числе Java,-1 % 2 == -1
. То есть,%
это не обязательно традиционное математическое определение по модулю. Java, например, называет это «оператором остатка».Что касается побитовой оптимизации, в поразрядной арифметике «легко» можно выполнить только степень двойки по модулю. Вообще говоря, только по модулю степеней основания b "легко" можно сделать с представлением чисел с основанием b .
В основании 10, например, для неотрицательного
N
,N mod 10^k
просто принимая значащиеk
цифры.Ссылки
источник
-1 = -1 (mod 2)
, не уверен, к чему вы клоните - вы имеете в виду, что это не то же самое, что остаток IEEE 754?(a / b) / b + a % b == a
, что для операторов C-типа целые числа a и b, b ненулевые, а такжеabs(a % b) < abs(b)
с теми же условиями.(a / b)
*b + a % b == a
.Есть только простой способ найти числа по модулю 2 ^ i с помощью побитового вычисления.
Существует изобретательный способ решения случаев Мерсенна по ссылке, например n% 3, n% 7 ... Существуют особые случаи для n% 5, n% 255 и составные случаи, такие как n% 6.
Для случаев 2 ^ i, (2, 4, 8, 16 ...)
Более сложные объяснить сложно. Читайте, только если вам очень любопытно.
источник
Это работает только для степеней двойки (и часто только положительных), потому что они обладают уникальным свойством иметь только один бит, установленный на «1» в их двоичном представлении. Поскольку ни один другой класс чисел не обладает этим свойством, вы не можете создавать побитовые выражения и для большинства выражений модуля.
источник
Это особый случай, потому что компьютеры представляют числа в базе 2. Это можно обобщить:
(число) основание % основание x
эквивалентно последним x цифрам (числа) базы .
источник
Существуют модули, отличные от степеней двойки, для которых существуют эффективные алгоритмы.
Например, если x - 32-битное целое число без знака, тогда x% 3 = popcnt (x & 0x55555555) - popcnt (x & 0xaaaaaaaa)
источник
По модулю "7" без оператора "%"
источник
Без использования побитового
&
оператора и ( ) в двоичном формате нет. Эскиз доказательства:Предположим, что существует такое значение k , что
x & k == x % (k + 1)
, но k! = 2 ^ n - 1 . Тогда, если x == k , выражениеx & k
кажется «работает правильно», и результат будет k . Теперь рассмотрим х == ки : если были какие -то «0» биты к , есть некоторые я больше 0 , которые ки могут быть выражены только с 1-бит в этих положениях. (Например, 1011 (11) должно стать 0111 (7), когда из него было вычтено 100 (4), в этом случае бит 000 становится 100, когда i = 4. ) Если бит из выражения k должен измениться с нуля одному, чтобы представить ки, то он не может правильно вычислить x% (k + 1) , которое в этом случае должно быть ki , но нет возможности для побитового логического значения и создания этого значения с учетом маски.источник
В этом конкретном случае (мод 7) мы все еще можем заменить% 7 поразрядными операторами:
Это работает, потому что 8% 7 = 1. Очевидно, этот код, вероятно, менее эффективен, чем простой x% 7, и, безусловно, менее читабелен.
источник
Используя bitwise_and, bitwise_or и bitwise_not, вы можете изменять любые битовые конфигурации на другие битовые конфигурации (т. Е. Этот набор операторов является «функционально полным»). Однако для таких операций, как модуль, общая формула обязательно будет довольно сложной, я бы даже не стал пытаться ее воссоздать.
источник