(Я работал над этим самостоятельно после того, как задал вопрос - я думал, что это будет сложнее, и я все равно буду приветствовать другие ответы, если есть лучшие!)
Решениедля целых чисел без знака относительно просто (как описано в ответе Джека Тула) и работает, перемещая условное условие (подразумеваемое) за пределы вычитания, так что мы всегда вычитаем меньшее число из большего, а не сравниваем потенциально упакованное значениев ноль:
if (a > b)
return a - b;
else
return b - a;
Это просто оставляет вопрос о целых числах со знаком.Рассмотрим следующий вариант:
if (a > b)
return (unsigned) a - (unsigned) b;
else
return (unsigned) b - (unsigned) a;
Мы можем легко доказать, что это работает, используя арифметику по модулю.Мы знаем, что a
и (unsigned) a
являются конгруэнтными по модулю UINT_MAX
.Кроме того, операция вычитания целого числа без знака совпадает с фактическим вычитанием по модулю UINT_MAX
, поэтому, комбинируя эти факты, мы знаем, что (unsigned) a - (unsigned) b
соответствует фактическому значению a - b
по модулю UINT_MAX
.Наконец, поскольку мы знаем, что фактическое значение a - b
должно быть между 0
и UINT_MAX-1
, мы знаем, что это точное равенство.