Вот новый ответ на старый вопрос, основанный на этом документе Microsoft Research и ссылках в нем.
Обратите внимание, что начиная с C11 и C ++ 11 семантика div
стала усечением до нуля (см. [expr.mul]/4
). Кроме того, для деления D
на d
C ++ 11 гарантирует следующее о частном qT
и остаткеrT
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));
где signum
соответствует -1, 0, +1, в зависимости от того, является ли его аргумент <, ==,> чем 0 ( исходный код см. в этих вопросах и ответах).
С усеченным делением, знак остатка равен знаком делимогоD
, то есть -1 % 8 == -1
. C ++ 11 также предоставляет std::div
функцию, которая возвращает структуру с членами quot
иrem
в соответствии с усеченным делением.
Возможны и другие определения, например, так называемое межэтажное перекрытие может быть определено в терминах встроенного усеченного участка.
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));
При половинном делении знак остатка равен знаку делителяd
. В таких языках, как Haskell и Oberon, есть встроенные операторы для полового деления. В C ++ вам нужно будет написать функцию, используя приведенные выше определения.
Еще один способ - евклидово деление , которое также можно определить в терминах встроенного усеченного деления.
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);
При евклидовом делении знак остатка всегда положительный .