啊,按位算术的乐趣。许多除法例程的副作用是模数 - 因此在少数情况下除法实际上应该比模数更快。我有兴趣查看您从中获得此信息的来源。具有乘法器的处理器使用乘法器具有有趣的除法例程,但是您只需另外两个步骤(乘法和减法)就可以从除法结果到模数,因此它仍然具有可比性。如果处理器具有内置的除法例程,您可能会看到它还提供了余数。
尽管如此,如果您真的想了解如何优化模运算,则需要研究模数运算的一小部分数论分支。例如,模块化算术对于生成幻方非常方便。
因此,在这种情况下,以下是对 x 示例的模数数学的一个非常低级的研究,它应该向您展示它与除法相比有多么简单:
也许考虑这个问题的更好方法是根据数基和模算术。例如,您的目标是计算 DOW mod 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 为模计算结果。
计算 8 位数字的 mod 7 结果可以以类似的方式执行。你可以像这样用八进制写一个 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
这是一个测试算法的小程序
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);
}
斯科特