Math.Round 및 MathF.Round가 올바르게 반올림된 결과를 반환합니다.

Math.Round(Double, Int32)MathF.Round(Single, Int32)해당 MidpointRounding 오버로드는 이제 입력의 정확한 값에 따라 요청된 소수 자릿수로 올바르게 반올림된 값을 반환합니다. 일부 입력은 이제 이전 릴리스와 다른(그리고 올바른) 결과로 반올림됩니다. 또한 인수에 digits 더 이상 상한이 없습니다.

도입된 버전

.NET 11 미리 보기 7

이전 동작

Math.Round(value, digits, mode) 이전에는 계산되었습니다Round(value * 10^digits, mode) / 10^digits. 일반적으로 정확하게 나타낼 수 없으므로 value * 10^digits 소수점 이하의 값은 정확한 중간점 또는 반올림 경계를 넘어 크기가 조정되어 올바르지 않은 결과가 생성될 수 있습니다. 크기가 큰 값은 크기 조정 단계에서 소수 비트가 완전히 손실될 수도 있습니다.

인수도 digits 0-15, double 0-6floatArgumentOutOfRangeException으로 제한되었습니다.

Math.Round(655.925, 2, MidpointRounding.AwayFromZero);            // 655.93              (incorrect)
Math.Round(1111111111111111.5, 1, MidpointRounding.AwayFromZero); // 1111111111111111.6  (incorrect)
Math.Round(1.5, 16, MidpointRounding.ToEven);                     // throws ArgumentOutOfRangeException

예를 들어 655.925 중간점 아래에 655.925 있는 로 655.924999999999954525…저장되므로 올바른 결과는 다음과 같습니다655.92.

새 동작

.NET 11부터 결과는 임의 정밀도 산술 연산을 사용하여 입력의 정확한 값에서 계산되고 반환된 값은 올바르게 반올림된 소수점 결과에 가장 가까운 표현 가능한 값입니다.

또한 음수가 아닌 digits 값은 허용되며 음수 값만 throw ArgumentOutOfRangeException됩니다. 형식을 왕복하는 데 필요한 전체 자릿수를 초과하는 자릿수(17개 double, 9개)는 float값을 변경하지 않고 그대로 둡니다. 이는 올바른 결과입니다.

Math.Round(655.925, 2, MidpointRounding.AwayFromZero);            // 655.92              (correct)
Math.Round(1111111111111111.5, 1, MidpointRounding.AwayFromZero); // 1111111111111111.5  (correct)
Math.Round(1.5, 16, MidpointRounding.ToEven);                     // 1.5                 (no longer throws)

파괴적 변경 유형

이 변경 사항은 동작 변경입니다.

변경 이유

이전 결과는 많은 수의 입력에 대해 잘못되었습니다. 지원되는 digits 범위에서 약 5%의 임의 값이 올바르게 반올림된 결과와 다릅니다. 이전 동작은 대용량 유한 입력도 거부하거나 잘못 처리했습니다. 새 구현은 IEEE 일치입니다. 입력의 정확한 값을 반올림하고 이미 생성된 값 value.ToString("F{digits}") 과 일치하는 가장 가까운 표현 가능한 결과를 반환합니다.

0-15와 0-6 digits 캡은 기존의 스케일 바이 접근 방식과 관련된 인위적인10^digits 제한이었습니다. 정확한 구현은 모든 숫자 수에 대해 정확하기 때문에 나중에 두 번째 동작 중단을 방지하기 위해 한도가 동시에 해제되었습니다.

자세한 내용은 dotnet/runtime#130574 참조하세요.

대부분의 코드는 수정된 결과에서 변경 및 이점이 필요하지 않습니다.

정확한 이전(잘못된) 출력에 의존하는 경우 이전 방법을 명시적으로 사용합니다(예 Math.Round(value * pow10, mode) / pow10: .). 또는 값이 통화와 같은 base-10 수량을 나타내는 경우를 사용하여 decimal 반올림을 수행합니다.

doublefloat 진 부동 소수점 형식이며 대부분의 소수 자릿수를 정확하게 나타낼 수 없습니다. 10진수 수량의 정확한 10진수 반올림을 선호 Decimal합니다. <System.Numerics.Decimal32>, <System.Numerics.Decimal64> 및 <System.Numerics.Decimal128> 은 확장된 범위와 기능을 가진 IEEE 754 소수점 기반 형식이며 이러한 유형의 작업에도 적합합니다.

영향을 받는 API

이러한 메서드에 위임하는 digits 숫자 인터페이스 진입점을 통해 동일한 수정된 동작 및 리프트된 범위 흐름(예 double.Round: , float.Round, Half.Round및 )입니다 NFloat.Round. Math.Round(Decimal, Int32) 단일 인수 Math.Round(Double)MathF.Round(Single) 오버로드는 영향을 받지 않습니다.