Ось нова відповідь на старе запитання, засноване на цій статті Microsoft Research та посиланнях на неї.
Зауважте, що починаючи з С11 та С ++ 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);
При евклідовому поділі знак залишку завжди позитивний .