System.Double을 '0'(숫자, 정수?)과 비교하는 올바른 방법
죄송합니다. 어리석은 질문 일 수 있지만 확실하게 알고 있어야합니다.
이 if
표현 이 있어요
void Foo()
{
System.Double something = GetSomething();
if (something == 0) //Comparison of floating point numbers with equality
// operator. Possible loss of precision while rounding value
{}
}
그 표현은
void Foo()
{
System.Double something = GetSomething();
if (something < 1)
{}
}
? 그러면 문제가있을 수 있습니다. if
예를 들어 0.9의 값과 함께 입력합니다 .
음, 값이 0에 얼마나 가까워 야합니까? "무한 정밀도"에서 0이 될 수있는 많은 부동 소수점 연산을 수행하면 결과가 0에 "매우 가깝게"될 수 있습니다.
일반적으로이 상황에서는 일종의 엡실론을 제공하고 결과가 해당 엡실론 내에 있는지 확인하려고합니다.
if (Math.Abs(something) < 0.001)
사용해야하는 엡실론은 응용 프로그램에 따라 다르며 수행중인 작업에 따라 다릅니다.
물론 결과가 정확히 0이 되어야한다면 간단한 동등성 검사가 좋습니다.
경우 something
이외의 작업의 결과에서 할당 된 something = 0
다음보다 효율적으로 사용 :
if(Math.Abs(something) < Double.Epsilon)
{
//do something
}
편집 :이 코드는 잘못되었습니다. Epsilon은 가장 작은 숫자이지만 0은 아닙니다. 숫자를 다른 숫자와 비교하려면 허용 가능한 허용 오차가 무엇인지 생각해야합니다. .00001 이상은 신경 쓰지 않는다고 가정 해 봅시다. 그것은 당신이 사용할 숫자입니다. 값은 도메인에 따라 다릅니다. 그러나 대부분 Double.Epsilon은 아닙니다.
귀하 something
는이며 double
라인에서 올바르게 식별했습니다.
if (something == 0)
우리는 double
왼쪽에 (lhs)와 int
오른쪽에 (rhs)가 있습니다.
당신이 LHS가 변환됩니다 생각처럼하지만 지금은 것 int
, 다음 ==
기호는 두 개의 정수를 비교합니다. 그것은 일어나는 일 이 아닙니다 . 변환 에서 double
에가 int
있다 명시 하고 "자동으로"일어날 수 없습니다.
대신 그 반대가 발생합니다. 우변은로 변환되고 double
, 다음 ==
기호는 두 배로 사이의 평등을 테스트하게된다. 이 변환은 암시 적 (자동)입니다.
글을 쓰는 것이 (일부는) 더 나은 것으로 간주됩니다
if (something == 0.0)
또는
if (something == 0d)
두 개의 복식을 비교하는 것이 즉각적이기 때문입니다. 그러나 컴파일러는 어떤 경우에도 동일한 작업을 수행하므로 스타일과 가독성의 문제 일뿐입니다.
경우에 따라 Jon Skeet의 답변에서와 같이 "관용"을 도입하는 것도 관련이 있지만 그 관용 double
도 마찬가지입니다. 이 수 의 과정이 될 1.0
당신이 원하는 경우에, 그러나 그것은으로 [가장 엄격하게 긍정적 인] 정수가 없습니다.
단순히 경고를 표시하지 않으려면 다음을 수행하십시오.
if (something.Equals(0.0))
물론 이것은 드리프트가 문제가되지 않는다는 것을 알고있는 경우에만 유효한 솔루션입니다. 나는 종종 0으로 나누려고하는지 확인하기 위해 이것을한다.
솔직히 평등하다고 생각하지 않습니다. 자신의 예를 고려하십시오 : something = 0.9 또는 0.0004. 첫 번째 경우에는 FALSE이고 두 번째 경우에는 TRUE입니다. 이 유형을 다루면서 나는 일반적으로 정밀도 비율을 정의하고 그 정밀도 내에서 비교합니다. 귀하의 필요에 따라 다릅니다. 뭔가 ...
if(((int)(something*100)) == 0) {
//do something
}
도움이 되었기를 바랍니다.
Here is the example presenting the problem (prepared in LinQPad - if you don't have it just use Console.Writeline
instead of Dump
method):
void Main()
{
double x = 0.000001 / 0.1;
double y = 0.001 * 0.01;
double res = (x-y);
res.Dump();
(res == 0).Dump();
}
Both x and y are theoretically same and equal to: 0.00001 but because of lack of "infinite precision" those values are slightly different. Unfortunately slightly enough to return false
when comparing to 0 in usual way.
'Development Tip' 카테고리의 다른 글
JMS 대신 Scala의 액터를 선호하는 디자인 결정은 무엇입니까? (0) | 2020.10.05 |
---|---|
클라이언트 측의 JavaScript require () (0) | 2020.10.05 |
ng-model 동적 할당 (0) | 2020.10.04 |
파이썬에서 문자열을 바이너리로 변환 (0) | 2020.10.04 |
Spyder / IPython / matplotlib에서 대화 형 플롯을 다시 얻으려면 어떻게해야합니까? (0) | 2020.10.04 |