9

When C has the / operator to divide two numbers, what is the purpose of having the div() library function?

Is there any scenario where / can't be used but div() can?

phuclv
  • 37,963
  • 15
  • 156
  • 475
Eight
  • 4,194
  • 5
  • 30
  • 51

6 Answers6

19

From the C99 Rationale document:

(7.20.6.2 The div, ldiv, and lldiv functions) Because C89 had implementation-defined semantics for division of signed integers when negative operands were involved, div and ldiv, and lldiv in C99, were invented to provide well-specified semantics for signed integer division and remainder operations. The semantics were adopted to be the same as in Fortran. Since these functions return both the quotient and the remainder, they also serve as a convenient way of efficiently modeling underlying hardware that computes both results as part of the same operation. [...] Now that C99 requires similar semantics for the division operator, the main reason for new programs to use div, ldiv or lldiv is to simultaneously obtain quotient and remainder.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    I wasn't aware of that. Too bad they didn't provide another one for the more useful behaviour where the 'remainder' is >=0. In my experience, when you actually care about how n/d is rounded for n<0, d>0, in almost all such cases you'd prefer to have it rounded towards -inf (which also makes % a proper modulus). Ah well. – greggo Jun 16 '15 at 17:05
  • You might consider adding your answer at [Why use div or ldiv in C/C++?](https://stackoverflow.com/q/4565272/608639). It looks like the canonical dup. – jww Nov 10 '18 at 14:52
6

Quoted from C Programming: A Modern Approach, 2nd Edition, chapter 26, Q & A section.

Q: Why do the div and ldiv functions exist? Can't we just use the / and % operators?

A: div and ldiv aren't quite the same as / and %. Recall from Section 4.1 that applying / and % to negative operands doesn't give a portable result in C89. If i or j is negative, whether the value of i / j is rounded up or down is implementation defined, as is the sign of i % j. The answer computed by div and ldiv, on the other hand, don't depend on the implementation. The quotient is rounded toward zero; the remainder is computed according to the formula n = q x d + r, where n is the original number, q is the quotient, d is the divisor, and r is the remainder. Here are a few examples:

 n      |  d     |  q     |  r
--------|--------|--------|--------
 7      |  3     |  2     |  1
-7      |  3     | -2     | -1
 7      | -3     | -2     |  1
-7      | -3     |  2     | -1

In C99, the / and % operators are guaranteed to produce the same result as div and ldiv.

Efficiency is the other reason that div and ldiv exist. Many machines have an instruction that can compute both the quotient and remainder, so calling div or ldiv may be faster than using the / and % operators separately.

mja
  • 1,273
  • 1
  • 20
  • 22
2

div_t is a structure, which contains a quotient member and a remainder member. For example :

typedef struct {
    int quot;
    int rem;
} div_t;

Some simple implementations of the div function use / and % operators. You can also see this topic.

Community
  • 1
  • 1
md5
  • 23,373
  • 3
  • 44
  • 93
2

div() returns the result of the division and the remainder. So you don't have to use % operator to find the remainder.

Snow Blind
  • 1,164
  • 7
  • 12
1

As other people have mentioned, div() will give you both the quotient and the remainder. This is because the (software) integer division algorithm that most C runtimes use computes both at the same time.

If the target computer does not have a hardware divider, the / operator typically gets turned into a call to div() and the remainder gets thrown away. The same thing happens with the % operator except that it's the quotient that gets tossed. So if you're doing something like this:

quot = a / b;
rem = a % b;

you're calling the divide routine twice (and divide is pretty slow if your computer doesn't do it in hardware). So it's faster to use div() to get both.

(Of course, it's also less readable and whether you actually gain any performance advantage depends on your specific platform and compiler. You should only ever switch to div() if you've determined that it's a performance bottleneck. Remember what Knuth said about premature optimization.)

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Chris Reuter
  • 1,458
  • 10
  • 8
  • 1
    This may have been true in ancient times, but compilers optimize for quite a while now, and they are smart enough to recognize nearby `/` and `%` with the same arguments, so they would translate that to the most efficient code. – T-Bull Feb 07 '19 at 12:35
-1

Too slow, yet redundant. At least glibc doc state that for case when gcc is used. I tried div to reimplement existing itoa() function (integer to ascii), expecting gcc to have builtin implementation for such a trivial thing, but gcc doesn't have it.

char *p = buf;
div_t d = {.quot = n};

while (1)
    d = div (d.quot, 10) ,
    *p++ = '0' + d.rem   ;

Above code was 5..7 times slower than with separate operators:

char *p = buf;

while (1)
    *p++ = '0' + n % 10,
    n /= 10;
  • What glibc doc states what, where, and can you please cite it? What GCC options did you compile with, any optimisations or no? What were the exact benchmarked times? – underscore_d Mar 13 '23 at 19:32