Мне настолько понравился этот вопрос, что я сделал его темой своего блога 4 июня 2013 года . Спасибо за отличный вопрос!
Легко найти большие ящики. Например:
a = 1073741823;
b = 134217727;
c = 134217727;
потому как b * c
переполняется до отрицательного числа.
Я бы добавил к этому тот факт, что в проверенной арифметике разница между a / (b * c)
и (a / b) / c
может быть различием между программой, которая работает, и программой, которая дает сбой. Если произведение b
и c
выходит за границы целого числа, первое будет аварийно завершено в проверенном контексте.
Для небольших положительных целых чисел, скажем, достаточно малых, чтобы поместиться в короткое, идентичность должна сохраняться.
Тимоти Шилдс только что опубликовал доказательство; Я представляю здесь альтернативное доказательство. Предположим, что все числа здесь являются неотрицательными целыми числами и ни одна из операций не переполняется.
Целочисленное деление x / y
находит такое значение q
, что q * y + r == x
, где 0 <= r < y
.
Таким образом, деление a / (b * c)
находит такое значение q1
, что
q1 * b * c + r1 == a
где 0 <= r1 < b * c
деление ( a / b ) / c
сначала находит такое значение qt
, что
qt * b + r3 == a
а затем находит такое значение q2
, что
q2 * c + r2 == qt
Замените это на, qt
и мы получим:
q2 * b * c + b * r2 + r3 == a
где 0 <= r2 < c
и 0 <= r3 < b
.
Две одинаковые вещи равны друг другу, поэтому имеем
q1 * b * c + r1 == q2 * b * c + b * r2 + r3
Предположим q1 == q2 + x
для некоторого целого числа x
. Подставьте это и решите для x
:
q2 * b * c + x * b * c + r1 = q2 * b * c + b * r2 + r3
x = (b * r2 + r3 - r1) / (b * c)
где
0 <= r1 < b * c
0 <= r2 < c
0 <= r3 < b
Может x
быть больше нуля? Нет. У нас есть неравенства:
b * r2 + r3 - r1 <= b * r2 + r3 <= b * (c - 1) + r3 < b * (c - 1) + b == b * c
Значит, числитель этой дроби всегда меньше b * c
, поэтому x
не может быть больше нуля.
Может x
быть меньше нуля? Нет, аналогичный аргумент оставлен читателю.
Поэтому целое число x
равно нулю, а значит q1 == q2
.