Nulik
Nulik

Reputation: 7370

Divide without losing remainder

In C, is it possible to divide a dividend by a constant and get the result and the remainder at the same time?

I want to avoid execution of 2 division instructions, as in this example:

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

Upvotes: 15

Views: 11096

Answers (4)

sashang
sashang

Reputation: 12214

I wouldn't worry about the instruction count because the x86 instruction set will provide a idivl instruction that computes the dividend and remainder in one instruction. Any decent compiler will make use of this instruction. The documenation here http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html describes the instruction as follows:

Performs unsigned division. Divides the contents of the double-word contained in the combined %edx:%eax registers by the value in the register or memory location specified. The %eax register contains the resulting quotient, and the %edx register contains the resulting remainder. If the quotient is too large to fit in %eax, it triggers a type 0 interrupt.

For example, compiling this sample program:

#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);
}

With gcc -S -O2 (-S saves the tempory file created that shows the asm listing), shows that the division and mod in the following lines

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

is effectively reduced to the following instruction:

idivl   28(%esp)

As you can see theres one instruction to perform the division and mod calculation. The idivl instruction remains even if the mod calculation in the C program is removed. After the idivl there are calls to mov:

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

These calls copy the quotient and the remainder onto the stack for the call to printf.

Update

Interestingly the function div doesn't do anything special other than wrap the / and % operators in a function call. Therefore, from a performance perspective, it will not improve the performance by replacing the lines

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

with a single call to div.

Upvotes: 15

Dave
Dave

Reputation: 11162

Don't waste your time with div() Like Nemo said, the compiler will easily optimize the use of a division followed by the use of a modulus operation into one. Write code that makes optimal sense, and let the computer remove the cruft.

Upvotes: 5

Gabe
Gabe

Reputation: 86738

You could always use the div function.

Upvotes: 3

John Flatness
John Flatness

Reputation: 33789

There's div():

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

Upvotes: 6

Related Questions