Подтвердить что ты не робот

Функция div полезна (stdlib.h)?

Существует функция, называемая div в C, С++ (stdlib.h)

div_t div(int numer, int denom);

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

Но C, С++ имеют/и% операторов.

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

4b9b3361

Ответ 1

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

  • div_t div(int, int)
  • ldiv_t ldiv(long, long)
  • lldiv_t lldiv(long long, long long)
  • 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;
}

Ответ 2

Да, это: он вычисляет коэффициент и остаток за одну операцию.

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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


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

Ответ 5

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

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

Ответ 6

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