stdlib procesos pause librerias control comandos c++ c integer-division

c++ - procesos - ¿Es útil la función div(stdlib.h)?



system cls (6)

Hay una función llamada div en C, C ++ (stdlib.h)

div_t div(int numer, int denom); typedef struct _div_t { int quot; int rem; } div_t;

Pero C, C ++ tienen / y% operadores.

Mi pregunta es: " Cuando hay / y% operadores, ¿es útil la función div ?"


Cuesta menos tiempo si necesita tanto valor. La CPU siempre calcula tanto el resto como el cociente al realizar la división. Si usa "/" una vez y "%" una vez, la CPU calculará el doble de ambos números.

(perdona mi pobre ingles, no soy nativo)


La función div () devuelve una estructura que contiene el cociente y el resto de la división del primer parámetro (el numerador) por el segundo (el denominador). Hay cuatro variantes:

  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 representa el tipo de entero más grande disponible en el sistema)

La estructura div_t se ve así:

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

La implementación simplemente usa los operadores / y % , por lo que no es exactamente una función muy complicada o necesaria, pero es parte del estándar C (como se define en [ISO 9899: 201x] [1]).

Vea la implementación en libc de GNU:

/* 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; }


La semántica de div () es diferente de la semántica de% y /, lo cual es importante en algunos casos. Es por eso que el siguiente código se encuentra en la implementación que se muestra en la respuesta de psYchotic:

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

% puede devolver una respuesta negativa, mientras que div () siempre devuelve un resto no negativo.

Verifique la entrada de WikiPedia , particularmente "div siempre se redondea hacia 0, a diferencia de la división entera ordinaria en C, donde el redondeo de números negativos depende de la implementación".


Probablemente porque en muchos procesadores la instrucción div produce ambos valores y siempre se puede contar con que el compilador reconozca que los operadores adyacentes / y% en las mismas entradas podrían unirse en una sola operación.


Sí, lo es: calcula el cociente y el resto en una operación.

Aparte de eso, se puede lograr el mismo comportamiento con / + % (y un optimizador decente los optimizará en una sola div todos modos).

Para resumir: si le importa eliminar los últimos bits de rendimiento, esta puede ser su función de elección, especialmente si el optimizador de su plataforma no es tan avanzado. Este es a menudo el caso de las plataformas integradas. De lo contrario, utilice la forma que encuentre más legible.


div() llenó una necesidad pre-C99: portabilidad

Pre C99 , la dirección de redondeo del cociente de a / b con un operando negativo dependía de la implementación. Con div() , la dirección de redondeo no es opcional, pero se especifica que sea hacia 0. div() proporcionó una división portátil uniforme. Un uso secundario fue la eficiencia potencial cuando el código necesitaba calcular tanto el cociente como el resto.

Con C99 y versiones posteriores, div() y / especificando la misma dirección redonda y con mejores compiladores optimizando los códigos a a/b a%b cercanos, la necesidad ha disminuido.

Esta fue la razón convincente para div() y explica la ausencia de udiv_t udiv(unsigned numer, unsigned denom) en la especificación C: Los problemas de los resultados dependientes de la implementación de a/b con operandos negativos no existen para unsigned incluso en pre-C99.