c中的模数优化

MrB*_*Sky 2 c optimization modulus

我正在尝试对我预先知道的一组整数进行模数运算的优化 分频器是 400-3500,而红利是高达 2^16 的正整数

我听说过黑客很高兴的魔术数字,但我找不到一种方法来获得一般数字模数的魔术数字。

如果不是通过幻数,我可以根据我对数字的信息进行优化吗?

har*_*old 5

你提到了 Hackers Delight,它有答案。请参阅常量除法部分,合并到编译器中(无符号)。实施那个。

然后,当然,不要每次做模数时都运行它,这会比简单的模数差得多。将你得到的 400-3500 的结果组成一个数组,然后在计算模数时,从该数组中获取参数。

那里给出的代码是

struct mu {unsigned M;     // Magic number, 
          int a;           // "add" indicator, 
          int s;};         // and shift amount. 

struct mu magicu(unsigned d) {
                           // Must have 1 <= d <= 2**32-1. 
   int p; 
   unsigned nc, delta, q1, r1, q2, r2; 
   struct mu magu; 

   magu.a = 0;             // Initialize "add" indicator. 
   nc = -1 - (-d)%d;       // Unsigned arithmetic here. 
   p = 31;                 // Init. p. 
   q1 = 0x80000000/nc;     // Init. q1 = 2**p/nc. 
   r1 = 0x80000000 - q1*nc;// Init. r1 = rem(2**p, nc). 
   q2 = 0x7FFFFFFF/d;      // Init. q2 = (2**p - 1)/d. 
   r2 = 0x7FFFFFFF - q2*d; // Init. r2 = rem(2**p - 1, d). 
   do {
      p = p + 1; 
      if (r1 >= nc - r1) {
         q1 = 2*q1 + 1;            // Update q1. 
         r1 = 2*r1 - nc;}          // Update r1. 
      else {
         q1 = 2*q1; 
         r1 = 2*r1;} 
      if (r2 + 1 >= d - r2) {
         if (q2 >= 0x7FFFFFFF) magu.a = 1; 
         q2 = 2*q2 + 1;            // Update q2. 
         r2 = 2*r2 + 1 - d;}       // Update r2. 
      else {
         if (q2 >= 0x80000000) magu.a = 1; 
         q2 = 2*q2; 
         r2 = 2*r2 + 1;} 
      delta = d - 1 - r2; 
   } while (p < 64 && 
           (q1 < delta || (q1 == delta && r1 == 0))); 

   magu.M = q2 + 1;        // Magic number 
   magu.s = p - 32;        // and shift amount to return 
   return magu;            // (magu.a was set above). 
}
Run Code Online (Sandbox Code Playgroud)

的方式来获得一个号码的模xy是事遂所愿(未测试,检查它)

uint64_t n = x;
// do division
n = ((n + magic[y].a) * magic[y].M) >> (32 + magic[y].s);
// get remainder
return x - y * n;
Run Code Online (Sandbox Code Playgroud)

使用 16 位幻数可能会比这做得更好,因此不会涉及 64 位整数。