c - 将商和提醒划分并存储在不同的数组中

标签 c

标准的 div() 函数返回一个 div_t 结构作为参数,例如:

/* div example */
#include <stdio.h>      /* printf */
#include <stdlib.h>     /* div, div_t */

int main ()
{
  div_t divresult;
  divresult = div (38,5);
  printf ("38 div 5 => %d, remainder %d.\n", divresult.quot, divresult.rem);
  return 0;
}

我的情况有点不同;我有这个

#define NUM_ELTS 21433
int main ()
{
  unsigned int quotients[NUM_ELTS];
  unsigned int remainders[NUM_ELTS];
  int i;

  for(i=0;i<NUM_ELTS;i++) {
      divide_single_instruction(&quotient[i],&reminder[i]);
  }
}

我知道用于除法的汇编语言在一条指令中完成所有事情,所以我需要在这里做同样的事情以节省 cpu 周期,这基本上是将商从 EAX 和提醒从 EDX 移动到我的数组所在的内存位置被存储。如果不在我的 C 代码中包含 asm {} 或 SSE 内在函数,如何做到这一点?它必须是可移植的。

最佳答案

由于您是就地写入数组(用商和余数替换分子和分母),您应该在写入数组之前将结果存储到临时变量。

void foo (unsigned *num, unsigned *den, int n) {
    int i;
    for(i=0;i<n;i++) {
        unsigned q = num[i]/den[i], r = num[i]%den[i];   
        num[i] = q, den[i] = r;
    }
}

生成这个主循环程序集

.L5:
        movl    (%rdi,%rcx,4), %eax
        xorl    %edx, %edx
        divl    (%rsi,%rcx,4)
        movl    %eax, (%rdi,%rcx,4)
        movl    %edx, (%rsi,%rcx,4)
        addq    $1, %rcx
        cmpl    %ecx, %r8d
        jg      .L5

有一些更复杂的情况,在第一次使用商和余数时,它有助于保存它们。例如,在通过试验除法测试素数时,您经常会看到这样的循环

for (p = 3; p <= n/p; p += 2)
    if (!(n % p)) return 0;

事实证明GCC does not use the remainder from the first division因此它执行了两次除法指令,这是不必要的。要解决此问题,您可以在第一次除法完成时保存余数,如下所示:

for (p = 3, q=n/p, r=n%p; p <= q; p += 2, q = n/p, r=n%p)
    if (!r) return 0;

这将结果速度提高了两倍。

所以一般来说,GCC 做得很好,特别是如果您在第一次计算时保存商和余数。

关于c - 将商和提醒划分并存储在不同的数组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34978046/

相关文章:

Android NDK 返回错误 "undefined reference to ' rand'”

c - 为什么除法运算通常会占用更多计算机资源?

c++ - vector * matrix 乘积效率问题

C: lseek() 相关问题

c - 为什么输入3次都不行

c - server.key.der 或 server.crt.der 大小相同

使用链表的 malloc() 和 free 的正确方法

c - 我找不到这个c程序中的错误

c - 监听:操作不支持错误

c - 在不更改位模式的情况下将 int8_t 作为 uint8_t 发送