Действительно ли там кто-либо альтернативен к использованию % (модуль) в C/C++?

Вы передаете указатель по значению.

Передайте ссылку на указатель, если вы хотите его обновить.

bool clickOnBubble(sf::Vector2i& mousePos, std::vector<Bubble *> bubbles, Bubble *& t)
33
задан Kirill Kobelev 21 December 2016 в 03:58
поделиться

11 ответов

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

однако, существует маленькое ответвление теории чисел, посвященной [1 111] Арифметика в остаточных классах , который требует исследования, если Вы действительно хотите понять, как оптимизировать операцию модуля. Модульная арифметика, например, очень удобна для генерации магические квадраты .

Так, в той вене, вот очень низкоуровневый взгляд в математике модуля для примера x, который должен показать Вам, как простой это может сравниться с подразделением:

<час>

, Возможно, лучший способ думать о проблеме с точки зрения оснований системы счисления и арифметики по модулю. Например, Ваша цель состоит в том, чтобы вычислить модификацию DOW 7, где DOW является 16-разрядным представлением дня недели. Можно записать это как:

 DOW = DOW_HI*256 + DOW_LO

 DOW%7 = (DOW_HI*256 + DOW_LO) % 7
       = ((DOW_HI*256)%7  + (DOW_LO % 7)) %7
       = ((DOW_HI%7 * 256%7)  + (DOW_LO%7)) %7
       = ((DOW_HI%7 * 4)  + (DOW_LO%7)) %7

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

Вычисления модификации 7 результатов 8-разрядного числа могут быть выполнены подобным способом. Можно записать 8-разрядное число в восьмеричном как так:

  X = a*64 + b*8 + c

, Где a, b, и c являются 3-разрядными числами.

  X%7 = ((a%7)*(64%7) + (b%7)*(8%7) + c%7) % 7
      = (a%7 + b%7 + c%7) % 7
      = (a + b + c) % 7

с тех пор 64%7 = 8%7 = 1

, Конечно, a, b, и c

  c = X & 7
  b = (X>>3) & 7
  a = (X>>6) & 7  // (actually, a is only 2-bits).

, самое большое значение для a+b+c 7+7+3 = 17. Так, Вам будет нужен еще один восьмеричный шаг. Полная (непротестированная) версия C могла быть записана как:

unsigned char Mod7Byte(unsigned char X)
{
    X = (X&7) + ((X>>3)&7) + (X>>6);
    X = (X&7) + (X>>3);

    return X==7 ? 0 : X;
}

я провел несколько моментов, пишущий версию PIC. Фактическая реализация немного отличается, чем описанный выше

Mod7Byte:
       movwf        temp1        ;
       andlw        7        ;W=c
       movwf        temp2        ;temp2=c
       rlncf   temp1,F        ;
       swapf        temp1,W ;W= a*8+b
       andlw   0x1F
       addwf        temp2,W ;W= a*8+b+c
       movwf        temp2   ;temp2 is now a 6-bit number
       andlw   0x38    ;get the high 3 bits == a'
       xorwf        temp2,F ;temp2 now has the 3 low bits == b'
       rlncf   WREG,F  ;shift the high bits right 4
       swapf   WREG,F  ;
       addwf        temp2,W ;W = a' + b'

 ; at this point, W is between 0 and 10


       addlw        -7
       bc      Mod7Byte_L2
Mod7Byte_L1:
       addlw        7
Mod7Byte_L2:
       return

, Вот liitle стандартная программа для тестирования алгоритма

       clrf    x
       clrf    count

TestLoop:
       movf        x,W
       RCALL   Mod7Byte
       cpfseq count
        bra    fail

       incf        count,W
       xorlw   7
       skpz
        xorlw        7
       movwf   count

       incfsz        x,F
       bra        TestLoop
passed:

Наконец для 16-разрядного результата (который я не протестировал), Вы могли записать:

uint16 Mod7Word(uint16 X)
{
 return Mod7Byte(Mod7Byte(X & 0xff) + Mod7Byte(X>>8)*4);
}

<час> Scott

47
ответ дан 27 November 2019 в 17:38
поделиться

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

кроме того, эти два обеспеченные фрагмента кода не делают того же самого. Во втором строка

if(fizzcount >= FIZZ)

всегда является ложью, таким образом, "FIZZ\n" никогда не печатается.

-4
ответ дан 27 November 2019 в 17:38
поделиться

У Вас есть доступ к каким-либо программируемым аппаратным средствам на встроенном устройстве? Как счетчики и такой? Если так, Вы смогли писать основанную на аппаратных средствах ультрасовременную единицу, вместо того, чтобы использовать моделируемый %. (Я сделал это однажды в VHDL. Не уверенный, если у меня все еще есть код все же.)

, Обратите внимание, Вы действительно говорили, что подразделение было в 5-10 раз быстрее. Вы рассмотрели выполнение разделения, умножения и вычитания к моделируемому модификация? (Редактирование: Неправильно понятый исходное сообщение. Я действительно думал, что это было нечетно, что подразделение было быстрее, чем модификация, они - та же операция.)

В Вашем конкретном случае, тем не менее, Вы проверяете на модификацию 6. 6 = 2*3. Таким образом, Вы могли, ВОЗМОЖНО, получить некоторые маленькие усиления, если бы Вы сначала проверили, был ли младший значащий бит 0. Что-то как:

if((!(x & 1)) && (x % 3))
{
    print("Fizz\n");
}

, Если бы Вы делаете это, тем не менее, я рекомендовал бы подтвердить, что Вы получаете любые усиления, yay для профилировщиков. И выполнение некоторого комментария. Я плохо себя чувствовал бы для следующего парня, который должен посмотреть на код иначе.

1
ответ дан 27 November 2019 в 17:38
поделиться

Необходимо действительно проверить встроенное устройство, в котором Вы нуждаетесь. Весь ассемблер, который я видел (x86, 68000) реализует модуль с помощью подразделения.

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

1
ответ дан 27 November 2019 в 17:38
поделиться

@Jeff V: Я вижу проблему с ним! (Кроме того Ваш исходный код искал модификацию 6, и теперь Вы по существу ищете модификацию 8). Вы продолжаете делать дополнительный +1! Надо надеяться, Ваш компилятор оптимизирует это далеко, но почему не просто тестируют, запускаются в 2 и переходят к MAXCOUNT включительно? Наконец, Вы возвращаете true каждый раз, когда (x+1) НЕ является делимым 8. Это то, что Вы хотите? (Я предполагаю, что это, но просто хотят подтвердить.)

0
ответ дан 27 November 2019 в 17:38
поделиться

Не то, чтобы это обязательно лучше, но у Вас мог быть внутренний цикл, который всегда повышается к ШИПЕНИЮ и внешнему циклу, который повторяет все это некоторое определенное количество раз. Вы затем, возможно, получили к особому случаю заключительные немного шагов, если MAXCOUNT не является равномерно делимым ШИПЕНИЕМ.

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

0
ответ дан 27 November 2019 в 17:38
поделиться

@Matthew является правильным. Попробуйте это:

int main() {
  int i;
  for(i = 0; i<=1024; i++) {
    if (!(i & 0xFF)) printf("& i = %d\n", i);
    if (!(i % 0x100)) printf("mod i = %d\n", i);
  }
}
3
ответ дан 27 November 2019 в 17:38
поделиться

Существуют издержки большую часть времени в использовании по модулю, которые не являются полномочиями 2. Это независимо от процессора как (AFAIK), даже процессоры с операторами модуля являются несколькими циклами медленнее для деления в противоположность операциям маски.

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

Однако одно эмпирическое правило состоит в том, чтобы выбрать размеры массива и т.д., чтобы быть полномочиями 2.

поэтому при вычислении дня недели, может также использовать %7 невнимательных при установке кольцевого буфера приблизительно 100 записей..., почему бы не сделать его 128. Можно затем записать % 128, и большинство (всех) компиляторов сделает этот & 0x7F

6
ответ дан 27 November 2019 в 17:38
поделиться

Если Вам действительно не нужна высокая производительность на нескольких встроенных платформах, не изменяйтесь, как Вы кодируете по причинам производительности, пока Вы не представляете!

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

4
ответ дан 27 November 2019 в 17:38
поделиться

При вычислении модификации числа некоторое питание два можно использовать поразрядное и оператор. Просто вычтите один из второго числа. Например:

x % 8 == x & 7
x % 256 == x & 255

Несколько протестов:

  1. Это только работы , если второе число является питанием два.
  2. Это только эквивалентно, если модуль всегда положителен. C и стандарты C++ не указывают знак модуля, когда первое число отрицательно (пока C++ 11, который делает гарантия, это будет отрицательно, который является тем, что большинство компиляторов уже делало). Поразрядное и избавляется от знакового бита, таким образом, это всегда будет положительно (т.е. это - истинный модуль, не остаток). Это кажется, что это - то, что Вы хотите так или иначе все же.
  3. Ваш компилятор, вероятно, уже делает это, когда он может, так в большинстве случаев не стоит делать его вручную.
35
ответ дан 27 November 2019 в 17:38
поделиться

Во встроенном мире операции "модуля", которые необходимо сделать, часто являются теми, которые ломаются приятно в битовые операции, которые можно сделать с '&'; и '|' и иногда'>>'.

1
ответ дан 27 November 2019 в 17:38
поделиться