Aquí hay una nueva respuesta a una pregunta anterior, basada en este artículo de Microsoft Research y sus referencias.
Tenga en cuenta que desde C11 y C ++ 11 en adelante, la semántica de se div
ha convertido en un truncamiento hacia cero (ver [expr.mul]/4
). Además, para D
dividir por d
, C ++ 11 garantiza lo siguiente sobre el cociente qT
y el restorT
auto const qT = D / d;
auto const rT = D % d;
assert(D == d * qT + rT);
assert(abs(rT) < abs(d));
assert(signum(rT) == signum(D));
donde se signum
asigna a -1, 0, +1, dependiendo de si su argumento es <, ==,> que 0 (consulte estas preguntas y respuestas para obtener el código fuente).
Con división truncada, el signo del resto es igual al signo del dividendoD
, es decir -1 % 8 == -1
. C ++ 11 también proporciona una std::div
función que devuelve una estructura con miembros quot
yrem
acuerdo con la división truncada.
Hay otras definiciones posibles, por ejemplo, la denominada división en suelo se puede definir en términos de la división truncada incorporada.
auto const I = signum(rT) == -signum(d) ? 1 : 0;
auto const qF = qT - I;
auto const rF = rT + I * d;
assert(D == d * qF + rF);
assert(abs(rF) < abs(d));
assert(signum(rF) == signum(d));
Con división en suelo, el signo del resto es igual al signo del divisor.d
. En lenguajes como Haskell y Oberon, hay operadores integrados para la división por suelo. En C ++, necesitaría escribir una función usando las definiciones anteriores.
Otra forma más es la división euclidiana , que también se puede definir en términos de la división truncada incorporada.
auto const I = rT >= 0 ? 0 : (d > 0 ? 1 : -1);
auto const qE = qT - I;
auto const rE = rT + I * d;
assert(D == d * qE + rE);
assert(abs(rE) < abs(d));
assert(signum(rE) != -1);
Con la división euclidiana, el signo del resto es siempre positivo .