[.net] .NET에서 기본적으로 은행가 반올림을 사용하는 이유는 무엇입니까?

설명서에 따르면이 decimal.Round방법은 대부분의 응용 프로그램에서 일반적이지 않은 반올림 알고리즘을 사용합니다. 그래서 나는 항상 더 자연스러운 반반 알고리즘을 수행하기 위해 사용자 정의 함수를 작성합니다.

public static decimal RoundHalfUp(this decimal d, int decimals)
{
    if (decimals < 0)
    {
        throw new ArgumentException("The decimals must be non-negative", 
            "decimals");
    }

    decimal multiplier = (decimal)Math.Pow(10, decimals);
    decimal number = d * multiplier;

    if (decimal.Truncate(number) < number)
    {
        number += 0.5m;
    }
    return decimal.Round(number) / multiplier;
}

아무도이 프레임 워크 디자인 결정의 이유를 알고 있습니까?

프레임 워크에 반 반올림 알고리즘을 구현 한 것이 있습니까? 아니면 관리되지 않는 Windows API일까요?

단순히 decimal.Round(2.5m, 0)3을 결과로 쓰지만 대신 2를 얻는 초보자에게는 오해의 소지가 있습니다 .



답변

아마도 더 나은 알고리즘이기 때문일 것입니다. 많은 반올림이 수행되는 동안, 모든 0.5는 반올림 및 반올림됩니다. 예를 들어 둥근 숫자를 더하면 실제 결과를 더 잘 추정 할 수 있습니다. 나는 그것이 어떤 사람들이 기대할 수는 없지만, 아마도 더 올바른 일이라고 말할 것입니다.


답변

다른 하나는 Banker의 알고리즘 ( 반올림에서 짝수로 )이 좋은 선택 인 이유에 대한 대답입니다 . 대부분의 합리적인 분포 에서 0의 방법을 반올림 하는 것만 큼 음의 또는 양의 바이어스를 겪지 않습니다 .

그러나 문제는 .NET이 Banker의 실제 반올림을 기본값으로 사용하는 이유였습니다. 그 대답은 Microsoft가 IEEE 754 표준을 따랐다는 것입니다. 이것은 MSDN의 Math.Round for Remarks 에도 언급되어 있습니다.

또한 .NET은 MidpointRounding열거 를 제공하여 IEEE에서 지정한 대체 방법을 지원합니다 . 물론 관계를 해결하는 데 더 많은 대안 을 제공 할 수는 있지만 IEEE 표준 만 충족하기로 선택합니다.


답변

“Microsoft 디자이너가 왜 이것을 기본으로 선택 했습니까?”라는 질문에 대답 할 수 없지만 추가 기능이 필요하지 않다는 점을 지적하고 싶습니다.

Math.Round당신이 지정할 수 있습니다 MidpointRounding:

  • 짝수-숫자가 다른 두 숫자의 중간에 있으면 가장 가까운 짝수로 반올림됩니다.
  • AwayFromZero-숫자가 다른 두 숫자의 중간에 있으면 0에서 가장 가까운 숫자로 반올림됩니다.

답변

십진법은 주로 돈으로 사용됩니다 . 은행가의 반올림은 돈을 다룰 때 일반적 입니다. 아니면 말할 수 있습니다.

대부분 십진법이 필요한 은행가입니다. 따라서“은행가의 반올림”

은행 반올림은 다음과 같은 경우 평균적으로 동일한 결과를 얻을 수 있다는 이점이 있습니다.

  • “송장 라인”세트를 추가하기 전에 반올림하십시오.
  • 또는 합산 한 다음 합계

추가하기 전에 반올림하면 컴퓨터 이전의 일에 많은 작업이 절약되었습니다.

(영국에서 우리가 10 진수 은행을 갔을 ​​때 반 펜스를 다루지 않았지만 수년 동안 여전히 반 펜스 동전이 있었고 상점은 종종 반 펜스로 끝나는 가격을 가졌습니다. 너무 많은 반올림)


답변

다음과 같이 Round 함수의 다른 과부하를 사용하십시오.

decimal.Round(2.5m, 0,MidpointRounding.AwayFromZero)

3 을 출력 합니다. 그리고 당신이 사용하는 경우

decimal.Round(2.5m, 0,MidpointRounding.ToEven)

당신은 은행가의 반올림을 얻을 것입니다.


답변