Я должен выполнить (a * b) % m
, но a
, b
, и m
являются 128-битными типами без знака, и переполнение во время умножения является большой возможностью.Как я могу все еще получить правильный ответ (вероятно, используя %
больше)?
Я пытаюсь реализовать модульную функцию экспоненты в Rust, где самый большой встроенный тип - u128
(который являетсямаксимум я могу использовать).Все три переменные действительно большие, поэтому (a * b) > 2^128
легкоЯ могу использовать a.overflowing_mul(b)
, чтобы определить, произошло ли переполнение, но я не знаю, как вернуться к результату переполнения (который можно рассматривать как (a * b) % 2^128
), чтобы получить (a * b) % m
.
MyМодульный код экспоненты выглядит следующим образом (в настоящее время поддержка переполнения не добавляется):
fn mod_exp(b: u128, e: u128, m: u128) {
(0..e).fold(1, |x, _| (x * b) % m)
// ^^^^^^^^^^^
}
С математической точки зрения:
(a * b) % m IS ACTUALLY (a * b) % B % m
| B = current base (2^128)
Примеры:
// Mathematical
(9 * 13) % 11 = 7
// Real (base 20):
(9 * 13) % (B = 20) % 11 = 6
^^^^^^^^^^ ^ should be 7
(8 * 4) % 14 = 4
(8 * 4) % (B = 16) % 14 = 0
^^^^^^^^^^ ^ should be 4