C++ 除了在C/C+中使用%(模数)之外,还有其他选择吗+;?

C++ 除了在C/C+中使用%(模数)之外,还有其他选择吗+;?,c++,c,modulo,embedded,C++,C,Modulo,Embedded,我曾在某个地方读到,模数运算符在小型嵌入式设备(如8位微控制器)上效率低下,这些设备没有整数除法指令。也许有人可以证实这一点,但我认为这一差异比整数除法运算慢5-10倍 除了保留一个计数器变量并在mod点手动溢出到0之外,还有其他方法吗? const int FIZZ = 6; for(int x = 0; x < MAXCOUNT; x++) { if(!(x % FIZZ)) print("Fizz\n"); // slow on some systems } const i

我曾在某个地方读到,模数运算符在小型嵌入式设备(如8位微控制器)上效率低下,这些设备没有整数除法指令。也许有人可以证实这一点,但我认为这一差异比整数除法运算慢5-10倍

除了保留一个计数器变量并在mod点手动溢出到0之外,还有其他方法吗?

const int FIZZ = 6;
for(int x = 0; x < MAXCOUNT; x++)
{
    if(!(x % FIZZ)) print("Fizz\n"); // slow on some systems
}
const int FIZZ=6;
对于(int x=0;x
vs:

我目前的做法是:

const int FIZZ = 6;
int fizzcount = 1;
for(int x = 1; x < MAXCOUNT; x++)
{
    if(fizzcount >= FIZZ) 
    {
        print("Fizz\n");
        fizzcount = 0;
    }
}
const int FIZZ=6;
int fizzcount=1;
对于(int x=1;x=嘶嘶声)
{
打印(“嘶嘶声”);
气泡数=0;
}
}

在嵌入式世界中,您需要执行的“模”运算通常可以很好地分解为位运算,您可以使用
&
|
执行,有时也可以使用
执行,除非您确实需要在多个嵌入式平台上实现高性能,不要因为性能原因而更改编码方式,直到您完成配置文件


为优化性能而笨拙编写的代码很难调试和维护。编写一个测试用例,并根据您的目标配置它。一旦你知道模的实际成本,然后决定替代解决方案是否值得编码。

这并不一定更好,但你可以有一个总是上升到嘶嘶作响的内环和一个重复一定次数的外环。如果
MAXCOUNT
不能被
FIZZ
平均整除,那么您可能需要对最后几个步骤进行特殊处理


也就是说,我建议您在预期的平台上进行一些研究和性能评测,以清楚了解您所面临的性能约束。可能会有更高效的地方用于您的优化工作。

您是否可以访问嵌入式设备上的任何可编程硬件?像柜台之类的?如果是这样,您可能可以编写一个基于硬件的mod单元,而不是使用模拟的%。(我曾经在VHDL中这样做过一次。但不确定我是否还有代码。)

请注意,你确实说过除法的速度要快5-10倍。你考虑过做除法、乘法和减法来模拟mod吗?(编辑:误解了原来的帖子。我确实认为分部比国防部快是很奇怪的,它们是相同的操作。)

但是,在您的特定情况下,您正在检查mod 6。6 = 2*3. 因此,如果您首先检查最低有效位是否为0,您可能会获得一些小的收益。比如:

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

如果你这么做了,我建议你确认一下你有什么收获,是的。做一些评论。我会为下一个不得不看代码的人感到难过。

如果你计算的是一个2的幂的数字,你可以使用位与运算符。从第二个数字中减去一。例如:

x % 8 == x & 7
x % 256 == x & 255
有几点需要注意:

  • 仅当第二个数字是2的幂时,此才有效

  • 只有当模量始终为正时,它才是等价的。C和C++标准在第一个数字为负数时(C++ 11,不保证它是否定的,这是大多数编译器已经做的),不指定模数的符号。以位为单位,去掉符号位,因此它将始终为正(即,它是真模,而不是余数)。但听起来这正是你想要的
  • 您的编译器可能已经在可能的情况下执行了此操作,因此在大多数情况下不值得手动执行。

  • @马修是对的。试试这个:

    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);
      }
    }
    
    intmain(){
    int i;
    
    对于(i=0;i@Jeff V:我发现了一个问题!(除此之外,您的原始代码正在寻找mod 6,而现在您基本上正在寻找mod 8)。您继续执行额外的+1!希望您的编译器能够优化它,但为什么不从2开始测试并转到包含MAXCOUNT的最大计数呢?最后,每次(x+1)都返回true不能被8整除。这就是你想要的吗?(我假设是,但只是想确认一下。)

    你真的应该检查你需要的嵌入式设备。我见过的所有汇编语言(x86,68000)都使用除法实现模


    实际上,除法汇编操作返回除法的结果和两个不同寄存器中的剩余值。

    啊,按位运算的乐趣。许多除法例程的一个副作用是模-因此在少数情况下,除法实际上应该比模快。我很想看看您获得此信息的来源来自。带乘法器的处理器有使用乘法器的有趣的除法例程,但您只需再执行两个步骤(乘法和减法)即可将除法结果转换为模,因此它仍然具有可比性。如果处理器有内置的除法例程,您可能会看到它还提供余数

    尽管如此,如果你真的想了解如何优化模运算,数论中还有一个小分支需要研究。例如,模运算非常方便生成

    因此,在这方面,这里有一个关于模的数学,以x为例,它应该向你展示它与除法相比有多简单:


    也许思考这个问题的一个更好的方式是从数字的角度 基数和模运算。例如,你的目标是计算道琼斯指数 mod 7,其中道琼斯指数是当天的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结果可以是pe
      X = a*64 + b*8 + c
    
      X%7 = ((a%7)*(64%7) + (b%7)*(8%7) + c%7) % 7
          = (a%7 + b%7 + c%7) % 7
          = (a + b + c) % 7
    
      c = X & 7
      b = (X>>3) & 7
      a = (X>>6) & 7  // (actually, a is only 2-bits).
    
    unsigned char Mod7Byte(unsigned char X)
    {
        X = (X&7) + ((X>>3)&7) + (X>>6);
        X = (X&7) + (X>>3);
    
        return X==7 ? 0 : X;
    }
    
    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:
    
    uint16 Mod7Word(uint16 X)
    {
     return Mod7Byte(Mod7Byte(X & 0xff) + Mod7Byte(X>>8)*4);
    }
    
    if(fizzcount >= FIZZ)
    x%y == (x-(x/y)*y)
    
    def mod6(number):
        while number > 7:
            number = (number >> 3 << 1) + (number & 0x7)
        if number > 5:
            number -= 6
        return number