Ваша функция:
uint Function(uint value)
{
return value * 0x123456D;
}
умножается на uint
(который работает так же, как целые числа по модулю 2**64
в так называемом unchecked
контексте) на нечетное число. Такое нечетное число имеет уникальный обратный, по модулю 2**64
. В данном случае это 0xE2D68C65u
, потому что, как вы можете проверить (синтаксис C #):
unchecked(0x123456Du * 0xE2D68C65u) == 1u
Это умножение ассоциативно и коммутативно. Итак, ваш «обратный» метод:
uint UndoFunction(uint value)
{
return value * 0xE2D68C65u;
}
(unckecked
контекст принят).
Для любого ввода x
, оба UndoFunction(Function(x))
и Function(UndoFunction(x))
возвращают вам оригинал x
.
PS! Чтобы найти модульное обратное 0xE2D68C65u
, я использовал что-то, кроме .NET. На самом деле GP / PARI нравится Чарльзу в его ответе. В GP вы можете сделать 1/Mod(19088749, 2^32)
или Mod(19088749, 2^32)^-1
. По умолчанию используется десятичная запись.