36

Is there a specific reason to use ldiv or div instead of '/' or '%' to divide/modulus two variables?

Sheraz
  • 569
  • 5
  • 11
  • 1
    Possible duplicate of [What is purpose of the div() library function?](https://stackoverflow.com/questions/11725884/what-is-purpose-of-the-div-library-function) – mja Nov 10 '18 at 03:09

5 Answers5

27

Yes. C99 §7.20.6.2/2 says:

The div, ldiv, and lldiv, functions compute numer / denom and numer % denom in a single operation.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Thanks, http://www.cppreference.com/wiki/numeric/c/div cleared it up for me as well. was missing the quotient and remainder. – Sheraz Dec 30 '10 at 18:46
27

The idea is that results from / and % can be determined from a single DIV instruction on the processor. So, historically, div() is used to provide an optimized way to get both.

However, I have found that newer compilers are able to optimize a / and % operation into a single divide anyway. For example, I've seen this optimization on Microsoft Visual C++. In these cases, div() really doesn't provide an advantage and, in fact, may even be slower if a call is involved.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
  • 5
    +1 for an explicit `don't even bother with that, your compiler's probably smarter than that anyway`. Now I'll just go and add italics to my answer ;) – Frédéric Hamidi Dec 30 '10 at 18:59
  • 8
    I would think that any compiler that is smart enough to optimize consecutive % and / operations into a single processor instruction, is also smart enough to inline a call to div(). :/ – Karl Knechtel Dec 30 '10 at 19:37
  • 1
    Unless you set some compiler option to *not* inline standard library calls. Why do I think such an option exists... perhaps from back in the day when I used to program in C? – President James K. Polk Dec 30 '10 at 19:40
  • @Karl: Just because a compiler is smart enough to inline a call does not necessarily mean it is configured or even has the ability to in all cases. At any rate, I had thought I had covered that with "may" and "if". – Jonathan Wood Dec 30 '10 at 22:18
9

That's supposed to be faster than using the / and % operators if you want to compute both the quotient and the remainder at the same time.

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • 1
    édéric: When you say "*supposed* to be faster", is the implication that it's sometimes not? – Stuart Golodetz Dec 30 '10 at 19:05
  • 1
    @Stuart, absolutely, see @Jonathan Wood's answer and my subsequent comment. Basically, if you're considering using the `ldiv` family of functions in order to increase performance, you're thinking your compiler isn't smart enough to optimize your `quotient+remainder` computation with something *cheaper* than a function call, or you're anticipating that `ldiv` and its ilk are compiler intrinsics and not actual functions. – Frédéric Hamidi Dec 30 '10 at 19:09
  • 6
    @Stuart Golodetz: Mandating that X must be faster than Y is the same as mandating that Y must be *slower* than X, which isn't a good business to get into. The only way to ensure that it's faster, would be to prohibit the optimizer, on seeing code that calculates both `/` and `%`, from using whatever optimizations the implementation uses in `ldiv`. But why should a compiler restrict itself so? – Steve Jessop Dec 30 '10 at 19:29
5

Short answer : not really in a modern environment.

People have explained why benefit of div is weak or even non-existent. It's actually even worse : div and friends introduce type coupling which hurts good practice (see drawback section below).

Advantage : probably none

As said in other answers, calling div instead of / and % most probably ensures that the operation is only done once at assembly level.

But in most modern contexts:

  1. The CPU has so well optimized mathematical operations that except in the innermost loop of a computation done zillion of times, any performance hit by repeating the operation is probably way smaller than other performance hits (like other code around, cache miss, etc.). => Benefit of div, if any, is generally negligible.
  2. Even when using / and % modern compilers do the right thing anyway by generating only one division instruction fetching quotient and remainder from that. => No actual benefit for div.

Drawback : div and friends tie your code to a specific type

If the exact type of the numbers (e.g. int or long) are statically known (that is, your code explicitly uses int or long always), using div for int and ldiv for long is okay.

But if you follow the good practice of programming in small parts avoiding unneeded assumptions, you quickly realize that using div and ldiv ties the code to types int or long respectively. On the contrary, / and % will automatically adjust to whatever type is actually used in the case at hand, keeping code cleaner.

This is especially visible in two cases :

  • you use typedef to abstract away actual types -- div is clumsy even in C !
  • you use templates to abstract away actual types -- div defeats templates.

Example

The sample below shows that code using '/' and '%' is clean, simple, and not tied to int, long, long long or whatever, whereas code using div and friends becomes clumsy.

Testing with int
my_math_func_div_WRONG  says 6
my_math_func_OVERKILL   says 6  // Works but overkill cast to long
my_math_func_GOOD   says 6      // No div no headache.

Testing with int in long type
my_math_func_div_WRONG  says 6
my_math_func_OVERKILL   says 6  // Works but overkill cast to long
my_math_func_GOOD   says 6      // No div no headache.

Testing with actual long
my_math_func_div_WRONG  says 70503280   // FAIL
my_math_func_OVERKILL   says 500000006
my_math_func_GOOD   says 500000006      // No div no headache.

Source code:

#include <iostream>

// '/' and '%' are smart about type.
// This code is simple and will work with int, long, longlong, char, whatever.
template<typename T>
T my_math_func_GOOD( T number )
{
    T quotient = number / 10;
    T remainder = number % 10;
    // do something
    return quotient + remainder;
}

// div and friends are not smart about type.
// How do you write code smart about type with them ?

// Plus adds dependency on C's stdlib.
#include <stdlib.h>
template<typename T>
T my_math_func_div_WRONG( T number )
{
    // This will always downcast to int. Defeats purpose of template.
    div_t result = div( number, 10 );
    T quotient = result.quot;
    T remainder = result.rem;
    // do something
    return quotient + remainder;
}

template<typename T>
T my_math_func_OVERKILL( T number )
{
    // This will always cast to long (up from int, OVERKILL, possibly down from long long, FAIL). Defeats purpose of template.
    ldiv_t result = ldiv( number, 10 );
    T quotient = result.quot;
    T remainder = result.rem;
    // do something
    return quotient + remainder;
}

template<typename T>
void my_math_func_test( T number )
{
    T n;
    n = my_math_func_div_WRONG( number );
    std::cout << "my_math_func_div_WRONG\tsays " << n << std::endl; // writes 6
    n = my_math_func_OVERKILL( number );
    std::cout << "my_math_func_OVERKILL\tsays " << n << std::endl; // writes 6
    n = my_math_func_GOOD( number );
    std::cout << "my_math_func_GOOD\tsays " << n << std::endl; // writes 6
}

// C99 allows absence of int argc, char **argv
int main()
{
    std::cout << std::endl << "Testing with int" << std::endl;
    my_math_func_test<int>( 42 );
    std::cout << std::endl << "Testing with int in long type" << std::endl;
    my_math_func_test<long>( 42 );
    std::cout << std::endl << "Testing with actual long" << std::endl;
    my_math_func_test<long>( 5000000042 );
    // std::cout << std::endl << "Testing with long long" << std::endl;
    // my_math_func_test<long long>( 50000000000000000042 );
}
Stéphane Gourichon
  • 6,493
  • 4
  • 37
  • 48
1

Okay, this is older, but I just stumbled here. The most important difference here is: The result of div() is defined. The C standard does not say how to round the quotient. That is because the compiler should be able to use the machine's implementation which depends on the CPU. Two different implementations exist: - rounding towards -infinity - rounding towards 0 .

div(), however is specified to do the latter, and is therefore portable.