Мне настолько понравился этот вопрос, что я сделал его темой своего блога 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.