C #에서 이중 값 비교
나는 double
라는 변수를 가지고 x
있습니다. 코드에서 x
의 값이 할당됩니다 내가 0.1
비교에 '만약'성명에서 그것을 확인 x
하고0.1
if (x==0.1)
{
----
}
불행히도 if
이야기에 들어 가지 언어
Double
또는 사용해야합니까double
?그 이유는 무엇입니까? 이에 대한 해결책을 제안 할 수 있습니까?
컴퓨터가 부동 소수점 값을 저장하는 방식으로 인해 표준 문제입니다. 여기에서 "부동 소수점 문제"를 검색하면 수많은 정보를 수 있습니다.
간단히 말해서 플로트 /은 더블 0.1
정확하게 저장할 수 없습니다 . 그것은 항상 약간 떨어져있을 것입니다.
decimal
십진수 표기법으로 숫자를 저장 하는 유형을 볼 수 있습니다 . 따라서 0.1
정확하게 표현할 수 있습니다.
이유를 알고 싶었습니다.
Float / double은 소수가 아닌 이진 분수로 저장됩니다. 설명하기 위해 :
12.34
십진수 표기법 (우리가 사용하는 것)은
1 × 1 + 2 * 10 0 + 3 × 10 -1 + 4 * 10 -2
컴퓨터는 base 2
: 10.01
의미를 제외하고는 동일한 방식으로 부동 소수점 숫자를 저장합니다 .
1 * 2 1 + 0 * 2 0 + 0 * 2-1 + 1 * 2-2
이제 십진법으로 완전히 표현할 수없는 숫자가 있다고 생각할 것입니다. 예를 들어, 1/3
10 진수 표기법은 0.3333333…
. 정확하게 표현할 수없는 숫자가 다르다는 점을 제외하면 이진 표기법은 똑같은 일이 발생합니다. 그중에는 숫자가 1/10
있습니다. 이진 표기법에서는 0.000110011001100…
.
이진 표기법은 사용하기 때문에 반올림 된 방식으로 저장됩니다. 따라서 당신의 문제.
double
및 Double
동일한 (아르 double
의 Double
와 같은)와 상호 교환 적으로 사용할 수 있습니다.
double을 다른 값과 값이있을 때의 문제는 double이 정확한 값이 아니라 근사값이라는 것입니다. 당신 그래서 x
이 0.1
그것을 설정 하면 실제로 0.100000001
또는 이와 비슷한 것으로 저장 될 수 있습니다 .
같은지 확인하는 대신 차이가 정의 된 최소 차이 (허용 오차)보다 작은 지 확인해야합니다. 다음과 같은 것 :
if (Math.Abs(x - 0.1) < 0.0000001)
{
...
}
과 a 의 조합 Math.Abs
에 대한 비교 광고가 필요 합니다 .X-Y
value
다음 확장 방법 접근 방식을 사용할 수 있습니다.
public static class DoubleExtensions
{
const double _3 = 0.001;
const double _4 = 0.0001;
const double _5 = 0.00001;
const double _6 = 0.000001;
const double _7 = 0.0000001;
public static bool Equals3DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _3;
}
public static bool Equals4DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _4;
}
...
ToString
꽤 안전한 확장을 믿지 않는 한 double에서 메소드를 거의 호출하지 않기 때문에 .
그럼 당신은 당신은 수 x
와 y
같은
if(x.Equals4DigitPrecision(y))
반올림 때문에 부동 소수점 수를 비교하는 것이 항상 정확하게 수행되는 것이 아닙니다. 비교하기 위해서
(x == .1)
컴퓨터는 아버지를 비교한다
(x - .1) vs 0
시스템에서 부동 소수점 숫자가 표시되는 방식으로 인해 sybtraction의 결과를 항상 정확하게 다시 수는 표시됩니다. 따라서 0이 아닌 값을 등급 조건은로 평가 false
됩니다.
이 비교를 쉽게하기 위해
Math.Abs(x- .1) vs some very small threshold ( like 1E-9)
로부터 문서 :
비교 정밀도 Equals 방법은 두 값의 정밀도가 다르기 때문에 명백하게 동일한 두 값이 같지 않을 수 있으므로주의해서 사용해야합니다. 다음 예제에서는 Double 값 .3333과 1을 3으로 나누어 반환 된 Double이 같지 않다고보고합니다.
...
동등성을 비교하는 대신 권장되는 한 가지 기술은 두 값 간의 허용 가능한 차이 한계를 정의하는 것입니다 (예 : 값 중 하나의 .01 %). 두 값 간의 차이의 절대 값이 해당 마진보다 작거나 같으면 차이는 정밀도 차이로 인한 것일 수 있으므로 값이 같을 가능성이 있습니다. 다음 예제에서는이 기술을 사용하여 이전 코드 예제에서 같지 않은 것으로 확인 된 두 Double 값인 .33333과 1/3을 비교합니다.
따라서 정말로 더블이 필요한 경우 문서에 설명 된 기술을 사용해야합니다. 가능하면 십진수로 변경하십시오. 더 느리지 만 이러한 유형의 문제는 발생하지 않습니다.
Double과 double은 동일합니다.
이유는 http://www.yoda.arachsys.com/csharp/floatingpoint.html을 참조 하십시오 . 간단히 말해서, double은 정확한 유형이 아니며 "x"와 "0.1"사이의 미세한 차이가이를 제거합니다.
부동 소수점 값의 정확한 비교는 반올림 및 내부 표현 문제로 인해 항상 작동하지 않는 것으로 알려져 있습니다.
부정확 한 비교를 시도하십시오.
if (x >= 0.099 && x <= 0.101)
{
}
다른 대안은 10 진수 데이터 유형을 사용하는 것입니다.
사용 decimal
. 이 "문제"가 없습니다.
1) Double 또는 double을 사용해야합니까 ???
Double
그리고 double
같은 것입니다. double
클래스 System.Double
의 별칭으로 작동하는 C # 키워드입니다 . 가장 일반적인 것은 별칭을 사용하는 것입니다! string
( System.String
), int
( System.Int32
)도 동일
기본 제공 형식 테이블 (C # 참조) 도 참조하세요.
Double (일부 언어에서는 float라고 함)은 반올림 문제로 인해 문제가 발생하며 대략적인 값이 필요한 경우에만 좋습니다.
Decimal 데이터 유형은 원하는 작업을 수행합니다.
참고로 decimal과 Decimal은 .NET C #에서 동일하며 double 및 Double 유형과 마찬가지로 둘 다 동일한 유형을 참조합니다 (10 진수와 double은 보시다시피 매우 다릅니다).
Decimal 데이터 유형에는 이와 관련된 비용이 있으므로 루프 등을보고있는 경우주의해서 사용하십시오.
Java 코드 기반에서 팁을 가져 와서 .CompareTo
제로 비교를 사용 하고 테스트하십시오. 이것은 .CompareTo
함수가 정확한 방식으로 부동 소수점 등식을 고려 한다고 가정합니다 . 예를 들어
System.Math.PI.CompareTo(System.Math.PI) == 0
이 술어는를 반환해야합니다 true
.
일반적으로 :
이중 표현은 대부분의 경우 충분하지만 일부 상황에서는 비참하게 실패 할 수 있습니다. 완전한 정밀도가 필요한 경우 (금융 애플리케이션에서와 같이) 십진수 값을 사용하십시오.
복식과 관련된 대부분의 문제는 직접 비교에서 비롯된 것이 아니라 반올림 및 분수 오류 (특히 곱셈 및 나눗셈)로 인해 값을 기하 급수적으로 방해하는 여러 수학 연산의 누적 결과로 사용됩니다.
코드가 다음과 같은 경우 논리를 확인하십시오.
x = 0.1
if (x == 0.1)
실패하지 않아야합니다. X 값이 더 복잡한 수단이나 작업으로 계산되면 디버거에서 사용하는 ToString 메서드가 스마트 반올림을 사용하고있을 가능성이 큽니다. 아마도 동일한 작업을 수행 할 수 있습니다 (너무 위험한 경우 다시 소수점 사용) :
if (x.ToString() == "0.1")
부동 소수점 숫자 표현은 (float이 내부적으로 저장되는 방식 때문에) 악명 높게 부정확합니다. 예를 들어 x는 실제로 0.0999999999 또는 0.100000001 일 수 있으며 조건이 실패합니다. float가 같은지 확인하려면 특정 허용 오차 내에서 같은지 여부를 지정해야합니다.
즉
if(Math.Abs(x) - 0.1 < tol) {
// Do something
}
// number of digits to be compared
public int n = 12
// n+1 because b/a tends to 1 with n leading digits
public double Epsilon { get; } = Math.Pow(10, -(n+1));
public bool IsEqual(double a, double b)
{
if (Math.Abs(a)<= double.Epsilon || Math.Abs(b) <= double.Epsilon)
return Math.Abs(a - b) <= double.Epsilon;
return Math.Abs(1.0 - a / b) <= Epsilon;
}
참고 URL : https://stackoverflow.com/questions/1398753/comparing-double-values-in-c-sharp
'ProgramingTip' 카테고리의 다른 글
키에서 양식 양식 방지 입력 (0) | 2020.12.06 |
---|---|
Laravel 5 클래스 'form'을 수 없습니다. (0) | 2020.12.06 |
생성기 / 반복자에서 항목 수를 계산하는 가장 짧은 방법은 무엇입니까? (0) | 2020.12.06 |
iOS로 라이선스에서 이미지로드 (0) | 2020.12.06 |
쉘에서 마지막으로 캐치 작성 시도 (0) | 2020.12.06 |