Ах, радости побитовой арифметики. Побочным эффектом многих процедур деления является модуль - поэтому в некоторых случаях деление должно быть быстрее, чем модуль. Мне интересно видеть источник, из которого вы получили эту информацию. У процессоров с множителями есть интересные процедуры деления, использующие множитель, но вы можете перейти от результата деления к модулю всего за два шага (умножить и вычесть), так что он все еще сопоставим. Если в процессоре есть встроенная подпрограмма деления, вы, вероятно, увидите, что он также предоставляет остаток.
Тем не менее, есть небольшая ветвь теории чисел, посвященная Модульная арифметика , которая требует изучения, если вы действительно хотите понять, как оптимизировать работу модуля. Например, модульная арифметика очень удобна для генерации магических квадратов .
Итак, в этом ключе очень низкоуровневый взгляд на математику модуля для примера 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.
Вычисление результата mod 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