Полезна ли функция div (stdlib.h)? - PullRequest
16 голосов
/ 16 июля 2011

В C, C ++ (stdlib.h) есть функция с именем div

div_t div(int numer, int denom);

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

Но в C, C ++ есть операторы / и%.

Мой вопрос: « Когда есть операторы / и%, полезна ли функция div

Ответы [ 6 ]

16 голосов
/ 16 июля 2011

Да, это так: вычисляет частное и остаток в операции one .

Помимо этого, такое же поведение может быть достигнуто с помощью / + % (иприличный оптимизатор все равно оптимизирует их в один div.

Чтобы подвести итог: если вы хотите выжать последние биты производительности, это может быть вашей функцией выбора, особенно еслиОптимизатор на вашей платформе не такой продвинутый.Это часто бывает для встроенных платформ.В противном случае используйте любой способ, который вы считаете более читабельным.

13 голосов
/ 16 июля 2011

Функция div () возвращает структуру, которая содержит частное и остаток от деления первого параметра (числителя) на второй (знаменатель). Есть четыре варианта:

  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 представляет самый большой целочисленный тип, доступный в системе)

Структура div_t выглядит следующим образом:

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

Реализация просто использует операторы / и %, поэтому это не совсем сложная или необходимая функция, но она является частью стандарта C (как определено в [ISO 9899: 201x] [1] ).

См. Реализацию в 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;
}
9 голосов
/ 16 июля 2011

Семантика div () отличается от семантики% и /, что важно в некоторых случаях. Вот почему следующий код находится в реализации, показанной в ответе psYchotic:

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

% может возвращать отрицательный ответ, тогда как div () всегда возвращает неотрицательный остаток.

Проверьте запись WikiPedia , в частности, "div всегда округляет до 0, в отличие от обычного целочисленного деления в C, где округление для отрицательных чисел зависит от реализации."

7 голосов
/ 09 сентября 2014

div() заполнено до C99: мобильность

До C99 , направление округления частного a / b с отрицательным операндом зависело от реализации. При div() направление округления не является обязательным, но указывает в направлении 0. div() при условии равномерного переносимого деления. вторичное использование было потенциальной эффективностью, когда код, необходимый для вычисления как частного, так и остатка.

С C99 и более поздними версиями, div() и /, указывающими одинаковое направление раунда, и с лучшими компиляторами, оптимизирующими близлежащий код a/b и a%b, необходимость уменьшилась.


Это было убедительной причиной для div() и , это объясняет отсутствие udiv_t udiv(unsigned numer, unsigned denom) в спецификации C: проблем, связанных с реализацией результатов a/b с отрицательными операндами, не существует для unsigned даже до C99.

1 голос
/ 16 июля 2011

Возможно, потому что на многих процессорах инструкция div производит оба значения, и вы всегда можете рассчитывать на то, что компилятор распознает, что смежные операторы / и% на одних и тех же входах могут быть объединены в одну операцию.

0 голосов
/ 16 июля 2011

Это стоит меньше времени, если вам нужны оба значения. CPU всегда вычисляет и остаток, и частное при выполнении деления. Если использовать "/" один раз и "%" один раз, процессор вычислит дважды оба числа.

(простите мой плохой английский, я не родной)

...