19

There is a function called div in C,C++ (stdlib.h)

div_t div(int numer, int denom);

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

But C,C++ have / and % operators.

My question is: "When there are / and % operators, Is div function useful?"

ldav1s
  • 15,885
  • 2
  • 53
  • 56
Amir Saniyan
  • 13,014
  • 20
  • 92
  • 137
  • it was already answered in [this question](http://stackoverflow.com/a/11726016/995714) – phuclv Sep 13 '14 at 04:27
  • 4
    Possible duplicate of [What is purpose of the div() library function?](https://stackoverflow.com/questions/11725884/what-is-purpose-of-the-div-library-function) (Note to non-Trafalmadorians: Linear time doesn't matter. That question got some better, more modern answers than this one did.) – underscore_d Jun 16 '19 at 16:49
  • Its answers focus excessively on one detail that stopped mattering in C99, which was 20 years ago... – underscore_d Jun 17 '19 at 19:34

6 Answers6

18

Yes, it is: it calculates the quotient and remainder in one operation.

Aside from that, the same behaviour can be achieved with /+% (and a decent optimizer will optimize them into a single div anyway).

In order to sum it up: if you care about squeezing out last bits of performance, this may be your function of choice, especially if the optimizer on your platform is not so advanced. This is often the case for embedded platforms. Otherwise, use whatever way you find more readable.

Vlad
  • 35,022
  • 6
  • 77
  • 199
  • 1
    A decent optimizer will replace `/` and `%` with two multiplies, a bit shift, and a subtraction (in most cases). – Ben Voigt Jul 16 '11 at 15:13
  • @Vlad: Do you mean calculating the quotient and remainder in one operation is so important that a new function defined? – Amir Saniyan Jul 16 '11 at 15:14
  • @Ben: are 2 multiplies, bit shift and subtraction really faster than one `DIV` instruction (on Intel family)? – Vlad Jul 16 '11 at 15:16
  • 10
    Historically it was; for a long time, division was a very expensive operation on CPUs, so any assistance from the compiler was welcome. Now, it's not as big a deal but there's no reason to *remove* `div()` from C, so it remains. – Jonathan Grynspan Jul 16 '11 at 15:19
  • @Ben, @Jonathan: Intel still advices to replace multiplication with division, see 9.2.4 in [this document](http://developer.intel.com/Assets/PDF/manual/248966.pdf). – Vlad Jul 16 '11 at 15:26
  • 2
    The multiplication tricks only work when the denominator is a constant. – R.. GitHub STOP HELPING ICE Jul 16 '11 at 15:39
  • @R: Right, I forgot about that restriction. – Ben Voigt Jul 16 '11 at 16:03
  • 1
    @Vlad: Doesn't that section recommend replacing division (by a constant) with multiplication? (And 128-bit division is very rare anyway) – Ben Voigt Jul 16 '11 at 16:06
  • @Ben: did I really write "replacing multiplication"? Oh, really I did. Sorry, it was a typo, my example was for confirming what you say, not denying. – Vlad Jul 16 '11 at 16:15
  • @BenVoigt in most architectures the div instruction return both quotient and remainder at the same time, so no need to multiply, shift or subtract – phuclv Sep 13 '14 at 04:16
  • @LưuVĩnhPhúc: So your very expensive divide gets you two outputs for the price of one. Multiply, shift, and subtract combination is still often cheaper. – Ben Voigt Sep 13 '14 at 04:34
  • @BenVoigt I mean in the case the compiler is using div instruction. Because it's only possible to convert a divide by constant to multiplication, so if you want to divide by a variable, you often have to use div instruction, which is most probably the case when someone uses div() – phuclv Sep 13 '14 at 04:41
  • @LưuVĩnhPhúc: I've seen plenty of people using `div` with a constant `10`, for conversion of binary to decimal. But yes, when the quotient is variable, the `div` instruction must be used. The `div` library function doesn't particularly help with that. – Ben Voigt Sep 13 '14 at 05:22
  • @Ben, @LưuVĩnhPhúc: well, `div` is not _guaranteed_ to be compiled into a specific processor instruction (after all, the target platform might lack one). _If_ multiplication/subtract is possible and faster, the optimizing compiler has to prefer that way. – Vlad Sep 22 '14 at 21:39
14

The div() function returns a structure which contains the quotient and remainder of the division of the first parameter (the numerator) by the second (the denominator). There are four variants:

  1. div_t div(int, int)
  2. ldiv_t ldiv(long, long)
  3. lldiv_t lldiv(long long, long long)
  4. imaxdiv_t imaxdiv(intmax_t, intmax_t (intmax_t represents the biggest integer type available on the system)

The div_t structure looks like this:

typedef struct
  {
    int quot;           /* Quotient.  */
    int rem;            /* Remainder.  */
  } div_t;

The implementation does simply use the / and % operators, so it's not exactly a very complicated or necessary function, but it is part of the C standard (as defined by [ISO 9899:201x][1]).

See the implementation in GNU libc:

/* Return the `div_t' representation of NUMER over DENOM.  */
div_t
div (numer, denom)
     int numer, denom;
{
  div_t result;

  result.quot = numer / denom;
  result.rem = numer % denom;

  /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where
     NUMER / DENOM is to be computed in infinite precision.  In
     other words, we should always truncate the quotient towards
     zero, never -infinity.  Machine division and remainer may
     work either way when one or both of NUMER or DENOM is
     negative.  If only one is negative and QUOT has been
     truncated towards -infinity, REM will have the same sign as
     DENOM and the opposite sign of NUMER; if both are negative
     and QUOT has been truncated towards -infinity, REM will be
     positive (will have the opposite sign of NUMER).  These are
     considered `wrong'.  If both are NUM and DENOM are positive,
     RESULT will always be positive.  This all boils down to: if
     NUMER >= 0, but REM < 0, we got the wrong answer.  In that
     case, to get the right answer, add 1 to QUOT and subtract
     DENOM from REM.  */

  if (numer >= 0 && result.rem < 0)
    {
      ++result.quot;
      result.rem -= denom;
    }

  return result;
}
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
psYchotic
  • 301
  • 1
  • 4
10

The semantics of div() is different than the semantics of % and /, which is important in some cases. That is why the following code is in the implementation shown in psYchotic's answer:

if (numer >= 0 && result.rem < 0)
    {
      ++result.quot;
      result.rem -= denom;
    }

% may return a negative answer, whereas div() always returns a non-negative remainder.

Check the WikiPedia entry, particularly "div always rounds towards 0, unlike ordinary integer division in C, where rounding for negative numbers is implementation-dependent."

Jørgen Fogh
  • 7,516
  • 2
  • 36
  • 46
  • 2
    This is not true. 1) When you truncate towards zero then the [remainder will be negative if `numer < 0`](http://ideone.com/J28Gk9). 2) Since C11 the built-in `/` and `%` are guaranteed to truncate towards zero, so `div` is defined to do the same as `/` and `%`. – Yakov Galka Aug 03 '16 at 09:59
  • Agree with [@ybungalobill](https://stackoverflow.com/questions/6718217/is-div-function-useful-stdlib-h/25734132#comment64854839_6718710). "whereas div() always returns a non-negative remainder." is incorrect. Try `printf("%d\n", div(-7,2).rem);` I'd expect code will return `-1`. – chux - Reinstate Monica Oct 31 '18 at 12:39
7

div() filled a pre-C99 need: portability

Pre C99, the rounding direction of the quotient of a / b with a negative operand was implementation dependent. With div(), the rounding direction is not optional but specified to be toward 0. div() provided uniform portable division. A secondary use was the potential efficiency when code needed to calculate both the quotient and remainder.

With C99 and later, div() and / specifying the same round direction and with better compilers optimizing nearby a/b and a%b code, the need has diminished.


This was the compelling reason for div() and it explains the absence of udiv_t udiv(unsigned numer, unsigned denom) in the C spec: The issues of implementation dependent results of a/b with negative operands are non-existent for unsigned even in pre-C99.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

Probably because on many processors the div instruction produces both values and you can always count on the compiler to recognize that adjacent / and % operators on the same inputs could be coalesced into one operation.

Richard Pennington
  • 19,673
  • 4
  • 43
  • 72
0

It costs less time if you need both value. CPU always calculate both remainder and quotient when performing division. If use "/" once and "%" once, cpu will calculate twice both number.

(forgive my poor English, I'm not native)

cuihao
  • 351
  • 2
  • 12
  • 4
    -1: That's not strictly correct, since the compiler will probably optimize it anyway. In addition, div() has to perform an extra check in order to guarantee that the result is non-negative. – Jørgen Fogh Jul 16 '11 at 16:27
  • 1
    @Jørgen Fogh The assertion "div() has to perform an extra check" is not strictly correct. Various processors provide the quotient and remainder as specified by `div()` without resorting to an "extra check". It is a platform dependent issue. A check may or may be needed. – chux - Reinstate Monica Sep 08 '14 at 22:44