문제

마틴 파울러 머니 클래스가 있습니다 돈 할당 루틴이 있습니다. 이 루틴은 반올림을 통해 가치를 잃지 않고 주어진 비율 목록에 따라 돈을 할당합니다. 결과에 대한 나머지 값을 전파합니다.

예를 들어, "비율"(1, 1, 1)에 의해 할당 된 $ 100는 양보 ($ 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;
}

(이 질문을 위해 더 간단하게하기 위해 돈 유형을 오랫동안 대체 할 자유를 얻었습니다.)

문제는 그것이 정확하다는 것을 어떻게 알 수 있습니까? 최종 루프를 제외하고는 모두 자명 한 것 같습니다. 기능이 정확하다는 것을 증명하기 위해서는 최종 루프에서 다음과 같은 관계가 사실임을 증명하기에 충분할 것입니다.

remainder < results.length

누구든지 그것을 증명할 수 있습니까?

도움이 되었습니까?

해결책

주요 통찰력은 각각의 나머지가 각각을 계산할 때 나머지의 합과 동일하다는 것입니다. result[i].

각 개인의 나머지는 반올림의 결과이므로 최대 1입니다. results.length 이러한 나머지이기 때문에 전체 나머지는 최대 results.length.

편집하다: 분명히 그것은 예쁜 상징이없는 증거가 아니므로 여기에 일부가 있습니다.
alt text

다른 팁

증거가 필요하지 않습니다.

기본 금액은 간단한 분할에 의해 배정되어 반올림됩니다. 따라서 할당 된 금액은 항상 총보다 작거나 같다.

나머지는 할당되지 않은 금액을 포함합니다. 항상 'I'보다 정수가 적습니다. 그래서 그는 단순히 돈이 사라질 때까지 각 수신기 1을 제공합니다.

단순한

사실을 사용하십시오

a = 바닥 (a/b)*b+(a%b)

호기심이 많은 비율이 결과 수보다 남은 나머지를 유발할 수 있기 때문에 정확하지 않다고 말하고 싶습니다. 그러므로 나는 제안한다 results[i % results.length].amount++;.

편집 : 나는 대답을 철회합니다. 오랫동안 호기심이없고 플로팅 포인트 모듈로는 도움이되지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top