划分而不会遗失余数

时间:2011-10-30 03:23:35

标签: c

在C中,是否可以将一个被除数除以一个常数并同时得到结果和余数?

我想避免执行2个除法指令,如下例所示:

val=num / 10;
mod=num % 10;

4 个答案:

答案 0 :(得分:14)

我不担心指令计数,因为x86指令集将提供idivl指令,用于计算一条指令中的被除数和余数。任何体面的编译器都会使用此指令。这里的文件http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html描述了如下指令:

  

执行无符号分割。划分双字的内容   包含在合并的%edx:%eax寄存器中的值   指定的寄存器或存储位置。 %eax寄存器包含   结果为商,%edx寄存器包含结果   剩余。如果商太大而不适合%eax,则触发a   0型中断。

例如,编译此示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
  int x = 39;
  int divisor = 1;
  int div = 0;
  int rem = 0;

  printf("Enter the divisor: ");
  scanf("%d", &divisor);
  div = x/divisor;
  rem = x%divisor;

  printf("div = %d, rem = %d\n", div, rem);
}

使用gcc -S -O2(-S保存创建的显示asm列表的临时文件),显示以下行中的除法和mod

div = x/divisor;
rem = x%divisor;

有效地缩减为以下指令:

idivl   28(%esp)

正如您所看到的那样,有一条指令用于执行除法和mod计算。即使删除了C程序中的mod计算,idivl指令仍然存在。 idivl之后有mov的电话:

movl    $.LC2, (%esp)
movl    %edx, 8(%esp)
movl    %eax, 4(%esp)
call    printf

这些调用将商和余数复制到堆栈上以调用printf。

更新

有趣的是,除了在函数调用中包装/和%运算符之外,函数div没有做任何特殊操作。因此,从性能角度来看,它不会通过替换行来提高性能

 val=num / 10;       
 mod=num % 10;

只需拨打div

答案 1 :(得分:5)

div()

div_t result = div(num, 10);
// quotient is result.quot
// remainder is result.rem

答案 2 :(得分:5)

不要浪费你的时间div()像Nemo说的那样,编译器会很容易地优化分区的使用,然后使用模数运算。编写具有最佳意义的代码,并让计算机删除残留物。

答案 3 :(得分:2)

您始终可以使用div功能。