Мартин Фаулер имеет класс Money, который имеет рутину распределения денег. Эта процедура распределяет деньги в соответствии с определенным списком коэффициентов, не теряя при этом значения при округлении. Он распределяет любое остаточное значение по результатам.
Например, 100 долларов, выделенных "отношениями" (1, 1, 1), будут давать ($ 34, $33, $33).
Вот функция allocate
:
public long[] allocate(long amount, long[] ratios) {
long total = 0;
for (int i = 0; i < ratios.length; i++) total += ratios[i];
long remainder = amount;
long[] results = new long[ratios.length];
for (int i = 0; i < results.length; i++) {
results[i] = amount * ratios[i] / total;
remainder -= results[i];
}
for (int i = 0; i < remainder; i++) {
results[i]++;
}
return results;
}
(Ради этого вопроса, чтобы сделать его проще, я взял на себя смелость заменить типы денег длинными.)
Вопрос в том, как я знаю, что это правильно? Все это кажется довольно очевидным, за исключением финальной петли. Я думаю, что для доказательства правильности функции было бы достаточно доказать, что в заключительном for-loop истинно следующее соотношение:
remainder < results.length
Кто-нибудь может это доказать?