Math.Round (2.5)가 3 대신 2를 반환하는 이유는 무엇입니까?
C #에서 결과 Math.Round(2.5)
는 2입니다.
3으로되어 있지 않습니까? C #에서 왜 2입니까?
첫째, 이것은 어쨌든 C # 버그가 아니며 .NET 버그입니다. C #은 언어 Math.Round
이며 구현 방법을 결정하지 않습니다 .
두 번째로, no- docs 를 읽으면 기본 반올림이 "짝수로 반올림"(은행가 반올림)임을 알 수 있습니다.
반환 값
형식 : System.Double
가장 가까운 정수 a. a의 분수 성분이 두 정수 사이의 중간에 있고, 그 중 하나는 짝수이고 다른 정수는 짝수입니다. 이 메소드는Double
정수 타입 대신에 리턴합니다 .설명
이 방법의 동작은 IEEE 표준 754, 섹션 4를 따릅니다. 이러한 종류의 반올림을 가장 가까운 반올림 또는 뱅커의 반올림이라고도합니다. 중간 지점 값을 한 방향으로 일관되게 반올림하여 발생하는 반올림 오류를 최소화합니다.
값 을 취하는 과부하 를 Math.Round
사용하여 중간 점을 반올림 하는 방법 을 지정할 수 있습니다 . 하나의 과부하가 있으며 각 과부하에는 해당하지 않습니다.MidpointRounding
MidpointRounding
Round(Decimal)
/Round(Decimal, MidpointRounding)
Round(Double)
/Round(Double, MidpointRounding)
Round(Decimal, Int32)
/Round(Decimal, Int32, MidpointRounding)
Round(Double, Int32)
/Round(Double, Int32, MidpointRounding)
이 불이행이 잘 선택되었는지 여부는 다른 문제입니다. ( MidpointRounding
.NET 2.0에서만 도입되었습니다. 그 전에는 원하는 동작을 직접 수행하지 않고도 구현할 수있는 쉬운 방법이 확실하지 않았습니다.) 특히 역사에 따르면 예상 한 동작 이 아니며 대부분의 경우 API 디자인의 기본적인 죄. Banker 's Rounding이 유용한 이유를 알 수 있지만 여전히 많은 사람들에게 놀라운 일입니다.
RoundingMode
더 많은 옵션을 제공 하는 가장 가까운 Java 등가 열거 형 ( )을 살펴 보는 것이 좋습니다 . (중간 지점 만 다루지는 않습니다.)
이를 짝수로 반올림 (또는 은행가 반올림)이라고하며, 이는 발생하는 누적 오류를 최소화하기위한 유효한 반올림 전략입니다 (MidpointRounding.ToEven)
. 이론은 항상 같은 방향으로 0.5 숫자를 반올림하면 오류가 더 빨리 발생한다는 것입니다 (라운드에서 짝수로 최소화해야 함) (a) .
다음에 대한 MSDN 설명을 보려면 다음 링크를 따르십시오.
Math.Floor
음의 무한대로 반올림합니다.Math.Ceiling
양의 무한대로 반올림합니다.Math.Truncate
0으로 올림 또는 내림합니다.Math.Round
가장 가까운 정수 또는 지정된 소수 자릿수로 반올림합니다. 마지막 자리가 고르거나 ( "Round(2.5,MidpointRounding.ToEven)
"2가되거나) 0에서 멀어 지도록 ( "Round(2.5,MidpointRounding.AwayFromZero)
"3이 됨) 반올림과 같이 두 가능성 사이에서 정확히 같은 거리에있을 경우 동작을 지정할 수 있습니다 .
다음 다이어그램과 표가 도움이 될 수 있습니다.
-3 -2 -1 0 1 2 3
+--|------+---------+----|----+--|------+----|----+-------|-+
a b c d e
a=-2.7 b=-0.5 c=0.3 d=1.5 e=2.8
====== ====== ===== ===== =====
Floor -3 -1 0 1 2
Ceiling -2 0 1 2 3
Truncate -2 0 0 1 2
Round(ToEven) -3 0 0 2 3
Round(AwayFromZero) -3 -1 0 2 3
참고 Round
가 소수점의 특정 번호로 반올림 할 수 있기 때문에 단순히, 그것은 것보다 훨씬 더 강력하다. 다른 모든 것들은 항상 제로 소수로 반올림합니다. 예를 들면 다음과 같습니다.
n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven); // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15
다른 함수에서는 곱하기 / 나누기 속임수를 사용해야 동일한 효과를 얻을 수 있습니다.
c = System.Math.Truncate (n * 100) / 100; // 3.14
d = System.Math.Ceiling (n * 100) / 100; // 3.15
(a) 물론이 이론은 데이터가 짝수 반 (0.5, 2.5, 4.5, ...)과 홀수 반 (1.5, 3.5, ...)에 걸쳐 상당히 균일하게 분포되어 있다는 사실에 달려 있습니다.
경우 모든 은 "반 값"(예를 들어) 고르게 있습니다 당신은 항상 반올림 것처럼 오류는 빠른 속도로 축적됩니다.
에서 MSDN, Math.Round (더블 A) 반환합니다 :
가장 가까운 정수 a. a의 분수 성분이 두 정수 사이의 중간에 있고, 그 중 하나는 짝수이고 다른 정수는 짝수입니다.
... 2와 3 사이의 중간 인 2.5는 짝수 (2)로 내림됩니다. 이것을 Banker 's Rounding (또는 Round-to-even)이라고하며 일반적으로 사용되는 반올림 표준입니다.
동일한 MSDN 기사 :
이 방법의 동작은 IEEE 표준 754, 섹션 4를 따릅니다. 이러한 종류의 반올림은 때때로 가장 가까운 반올림 또는 뱅커의 반올림이라고합니다. 중간 지점 값을 한 방향으로 일관되게 반올림하여 발생하는 반올림 오류를 최소화합니다.
MidpointRounding
모드 를 사용하는 Math.Round의 오버로드를 호출하여 다른 반올림 동작을 지정할 수 있습니다 .
MSDN에서 Math.Round
다음을 확인해야합니다 .
이 방법의 동작은 IEEE 표준 754, 섹션 4를 따릅니다. 이러한 종류의 반올림은 때때로 가장 가까운 반올림 또는 뱅커의 반올림이라고합니다.
Math.Round
오버로드 사용 동작을 지정할 수 있습니다 .
Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // gives 3
Math.Round(2.5, 0, MidpointRounding.ToEven); // gives 2
반올림의 특성
분수를 포함하는 숫자를 정수로 반올림하는 작업을 고려하십시오. 이 상황에서 반올림하는 과정은 반올림 할 숫자를 가장 잘 나타내는 정수를 결정하는 것입니다.
일반적으로 또는 '산술'반올림에서는 2.1, 2.2, 2.3 및 2.4가 2.0으로 반올림되는 것이 분명합니다. 및 2.6, 2.7, 2.8 및 2.9 내지 3.0.
2.5는 3.0보다 2.0에 가깝지 않습니다. 2.0과 3.0 중 하나를 선택하는 것은 귀하에게 달려 있습니다.
빼기 숫자 인 경우 -2.1, -2.2, -2.3 및 -2.4는 -2.0이됩니다. -2.6, 2.7, 2.8 및 2.9는 산술 반올림에서 -3.0이됩니다.
-2.5의 경우 -2.0과 -3.0 사이에서 선택해야합니다.
다른 형태의 라운딩
'반올림'은 소수점 이하 자릿수를 사용하여 다음 '전체'숫자로 만듭니다. 따라서 2.5와 2.6을 3.0으로 반올림 할뿐만 아니라 2.1과 2.2도 반올림합니다.
반올림하면 양수와 음수가 모두 0에서 멀어집니다. 예 : 2.5 ~ 3.0 및 -2.5 ~ -3.0.
'반올림'은 원치 않는 숫자를 잘라내어 숫자를 자릅니다. 이것은 숫자를 0으로 이동시키는 효과가 있습니다. 예 : 2.5 ~ 2.0 및 -2.5 ~ -2.0
가장 일반적인 형태 인 "은행가 반올림"에서 반올림 할 0.5는 반올림 또는 반올림되므로 반올림 결과는 항상 짝수입니다. 따라서 2.5는 2.0, 3.5-4.0, 4.5-4.0, 5.5-6.0 등으로 반올림됩니다.
'대체 반올림'은 반올림과 반올림 사이에서 0.5의 프로세스를 번갈아 표시합니다.
'무작위 반올림'은 전적으로 무작위로 0.5를 올림 또는 내림합니다.
대칭과 비대칭
반올림 함수는 모든 숫자를 0에서 반올림하거나 모든 숫자를 0으로 반올림하면 '대칭'이라고합니다.
양수를 0으로 반올림하고 음수를 0에서 멀어지게하는 경우 함수는 '비대칭'입니다. 2.5 내지 2.0; 및 -2.5 내지 -3.0.
또한 비대칭은 양수를 0에서 멀어지고 음수를 0으로 반올림하는 함수입니다. 예 : 2.5 내지 3.0; 및 -2.5 내지 -2.0.
대부분의 사람들은 대칭 반올림을 생각합니다. 여기서 -2.5는 -3.0으로 반올림되고 3.5는 4.0으로 반올림됩니다. (C #에서Round(AwayFromZero)
)
기본 MidpointRounding.ToEven
또는 은행가의 반올림 ( 2.5가 2가되고 4.5가 4가되는 등 )은 회계 보고서를 작성하기 전에 저를 찔렀으므로 이전에 발견 한 내용에 대해 몇 가지 단어를 작성하겠습니다. 이 게시물.
짝수로 내림하는이 은행가는 누구입니까 (영국 은행가 일 것입니다!)?
위키 백과에서
은행가 반올림이라는 용어의 기원은 여전히 모호합니다. 이 반올림 방법이 뱅킹의 표준 이었다면 증거를 찾기가 매우 어려웠습니다. 반대로, 유럽위원회 보고서의 섹션 2 유로 도입 및 통화 반올림은 은행에서 반올림에 대한 표준 접근법이 없었 음을 시사합니다. "반쯤"금액을 반올림하도록 지정합니다.
물론 은행이 많은 금액의 예금을받는 데 사용하지 않는 한, 특히 은행을 위해 매우 반올림하는 방법으로 보입니다. £ 2.4m를 입금하지만, £ 2m이라고합니다.
IEEE 표준 754는 1985 년으로 거슬러 올라가며 두 가지 반올림 방식을 제공하지만 표준에서 권장하는대로 은행가를 사용합니다. 이 위키 백과 기사 에는 언어가 반올림을 구현하는 방법에 대한 긴 목록이 있으며 (아래 중 하나라도 잘못된 경우 수정) 대부분 은행원을 사용하지 않고 학교에서 배운 반올림을 사용합니다.
- math.h의 C / C ++ round ()는 0에서 반올림합니다 (뱅커의 반올림 아님)
- Java Math.Round 는 0에서 반올림합니다 (결과를 바닥에 놓고 0.5를 더하며 정수로 캐스트). BigDecimal 에는 대안이 있습니다.
- 펄 은 C와 비슷한 방법을 사용합니다
- Javascript는 Java의 Math.Round와 동일합니다.
MSDN에서 :
기본적으로 Math.Round는 MidpointRounding.ToEven을 사용합니다. 대안은 "0에서 반올림"이 학교에서 더 일반적으로 가르치기 때문에 대부분의 사람들은 "올림에서 짝수"에 익숙하지 않습니다. .NET은 "0에서 반올림"하는 경향이 반올림보다 약간 더 자주 반올림하는 경향을 공유하지 않기 때문에 통계적으로 우수하므로 "둥근 반올림"으로 기본 설정됩니다 (반올림되는 숫자가 양수인 것으로 가정). )
http://msdn.microsoft.com/en-us/library/system.math.round.aspx
Silverlight는 MidpointRounding 옵션을 지원하지 않으므로 직접 작성해야합니다. 다음과 같은 것 :
public double RoundCorrect(double d, int decimals)
{
double multiplier = Math.Pow(10, decimals);
if (d < 0)
multiplier *= -1;
return Math.Floor((d * multiplier) + 0.5) / multiplier;
}
이를 확장으로 사용하는 방법을 포함하는 예는 .NET 및 Silverlight Rounding 게시물을 참조하십시오.
C # 응용 프로그램이 아닌 동안 SQL 서버가 0.5에서 1로 반올림되는이 문제가 발생했습니다. 따라서 두 가지 다른 결과가 나타납니다.
다음은 int / long 구현입니다. 이것이 Java가 반올림하는 방법입니다.
int roundedNumber = (int)Math.Floor(d + 0.5);
아마도 당신이 생각할 수있는 가장 효율적인 방법 일 것입니다.
double을 유지하고 decimal precision을 사용하려면 소수점 이하 자릿수를 기준으로 10의 지수를 사용하면됩니다.
public double getRounding(double number, int decimalPoints)
{
double decimalPowerOfTen = Math.Pow(10, decimalPoints);
return Math.Floor(number * decimalPowerOfTen + 0.5)/ decimalPowerOfTen;
}
소수점에 음수를 입력 할 수 있으며 단어도 좋습니다.
getRounding(239, -2) = 200
이 게시물에는 원하는 답변이 있습니다.
http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx
기본적으로 이것은 다음과 같습니다.
반환 값
자릿수와 같은 정밀도로 가장 가까운 숫자입니다. 값이 두 숫자 사이의 중간 인 경우 하나는 짝수이고 다른 하나는 홀수이면 짝수가 반환됩니다. 값의 정밀도가 자릿수보다 작은 경우 값이 변경되지 않은 상태로 반환됩니다.
이 방법의 동작은 IEEE 표준 754, 섹션 4를 따릅니다. 이러한 종류의 반올림은 때때로 가장 가까운 반올림 또는 뱅커의 반올림이라고합니다. 숫자가 0 인 경우, 이러한 종류의 반올림을 때로는 0을 향한 반올림이라고합니다.
Silverlight는 MidpointRounding 옵션을 지원하지 않습니다. MidpointRounding 열거 형을 추가하는 Silverlight의 확장 방법은 다음과 같습니다.
public enum MidpointRounding
{
ToEven,
AwayFromZero
}
public static class DecimalExtensions
{
public static decimal Round(this decimal d, MidpointRounding mode)
{
return d.Round(0, mode);
}
/// <summary>
/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
/// </summary>
/// <param name="d">A Decimal number to be rounded.</param>
/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
{
if ( mode == MidpointRounding.ToEven )
{
return decimal.Round(d, decimals);
}
else
{
decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
int sign = Math.Sign(d);
return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
}
}
}
출처 : http://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/
간단한 방법은 다음과 같습니다.
Math.Ceiling(decimal.Parse(yourNumber + ""));
맞춤 반올림 사용
public int Round(double value)
{
double decimalpoints = Math.Abs(value - Math.Floor(value));
if (decimalpoints > 0.5)
return (int)Math.Round(value);
else
return (int)Math.Floor(value);
}
이것은 모든 지옥처럼 추악하지만 항상 올바른 산술 반올림을 생성합니다.
public double ArithRound(double number,int places){
string numberFormat = "###.";
numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');
return double.Parse(number.ToString(numberFormat));
}
내가 해결 해야하는 방법은 다음과 같습니다.
Public Function Round(number As Double, dec As Integer) As Double
Dim decimalPowerOfTen = Math.Pow(10, dec)
If CInt(number * decimalPowerOfTen) = Math.Round(number * decimalPowerOfTen, 2) Then
Return Math.Round(number, 2, MidpointRounding.AwayFromZero)
Else
Return CInt(number * decimalPowerOfTen + 0.5) / 100
End If
End Function
소수점 이하 두 자리로 1.905를 사용하면 예상대로 1.91이되지만 Math.Round(1.905,2,MidpointRounding.AwayFromZero)
1.90이됩니다! Math.Round 메소드는 프로그래머가 겪을 수있는 대부분의 기본 문제에 대해 일관되지 않으며 사용할 수 없습니다. 내가 (int) 1.905 * decimalPowerOfTen = Math.Round(number * decimalPowerOfTen, 2)
반올림 해야하는 것을 반올림하지 않으려면 원인 을 확인 해야합니다.
참고 URL : https://stackoverflow.com/questions/977796/why-does-math-round2-5-return-2-instead-of-3
'Programing' 카테고리의 다른 글
jQuery로 5 초 동안 기다리는 방법? (0) | 2020.02.25 |
---|---|
배열에서 고유하지 않은 모든 값 (예 : 중복 / 둘 이상의 발생)을 가져옵니다. (0) | 2020.02.25 |
Git에서 원격으로 브랜치 이름 바꾸기 (0) | 2020.02.25 |
배열의 마지막 요소를 삭제하지 않고 얻는 가장 좋은 방법은 무엇입니까? (0) | 2020.02.25 |
폴더에있는 모든 파일의 파일 이름 가져 오기 (0) | 2020.02.25 |