[c#] 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
}

도움이 되었기를 바랍니다.


답변

다음은 문제를 보여주는 예제입니다 (LinQPad에서 준비 됨-없는 경우 방법 Console.Writeline대신 사용 Dump) :

void Main()
{
    double x = 0.000001 / 0.1;
    double y = 0.001 * 0.01;

    double res = (x-y);
    res.Dump();
    (res == 0).Dump();
}

x와 y는 모두 이론적으로 동일하고 0.00001과 같습니다. 그러나 “무한 정밀도”가 없기 때문에 이러한 값은 약간 다릅니다. 안타깝게도 false일반적인 방법으로 0과 비교할 때 약간만 반환 됩니다.


답변