Double.epsilon 평등,보다 큰, 작거나 작거나 동일하거나 동일하게 또는 동일합니다.

StackOverflow https://stackoverflow.com/questions/2411392

  •  18-09-2019
  •  | 
  •  

문제

http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

두 개의 부동 소수점 숫자가 동일하게 간주 될 수 있는지 여부를 결정하는 사용자 정의 알고리즘을 작성하는 경우, 두 값이 동일하게 간주되는 두 값에 대한 허용 가능한 절대 차이를 설정하기 위해 Epsilon 상수보다 큰 값을 사용해야합니다. (일반적으로, 그 차이의 마진은 엡실론보다 몇 배나 큽니다.)

그렇다면 이것은 실제로 비교에 사용될 수있는 엡실론이 아닌가? 나는 MSDN 문구를 정말로 이해하지 못한다.

여기 예제에서 엡실론으로 사용할 수 있습니까? - 플로트 및 이중 비교에 가장 효과적인 방법은 무엇입니까?

그리고 마지막으로 이것은 정말로 중요한 것처럼 보이므로 평등,보다 큰 것, 작거나 같거나 동등한 것보다 더 큰 평등에 대한 견고한 구현을하고 싶습니다.

도움이 되었습니까?

해결책

모르겠어요 무엇 그들은 썼을 때 담배를 피우고있었습니다. Double.Epsilon 0이 아닌 가장 작은 비 정규 플로팅 포인트 값입니다. 당신이 아는 것은 잘린 오류가 있으면 항상 더 큰 이 값보다. 훨씬 더 큰.

그만큼 System.Double 유형은 최대 15 자리까지 정확한 값을 나타낼 수 있습니다. 따라서 이중 값이든 간단한 1 차 추정치 x 상수와 동일합니다.

public static bool AboutEqual(double x, double y) {
    double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
    return Math.Abs(x - y) <= epsilon;
}

그래도 조심해야합니다. 잘림 오류가 축적 될 수 있습니다. 둘 다 x 그리고 y 계산 된 값이면 Epsilon을 늘려야합니다.

다른 팁

나는 평등을위한 견고한 구현,보다 큰 것보다 작거나 적은 것보다 크거나 동등한 것보다 더 크게 구현하고 싶습니다.

바이너리 플로팅 포인트 산술을 사용하고 있습니다.

바이너리 플로팅 포인트 산술은 길이, 질량, 충전, 시간 등과 같은 물리적 수량을 나타내도록 설계되었습니다.

아마도 당신은 사용하려는 바이너리 플로팅 포인트 산술을 사용하고 있습니다 : 물리적 수량에 대한 산술을 수행하는 것.

물리 수량의 측정은이를 측정하는 데 사용되는 장치의 정밀도에 따라 항상 특별한 정밀도를 갖습니다.

당신은 당신이 조작하는 수량에 대한 값을 제공하는 사람이기 때문에, 당신은 그 수량에 "오류 막대"가 무엇인지 아는 사람입니다. 예를 들어, "건물의 높이는 123.56 미터"수량을 제공하는 경우, 이것이 센티미터에 정확하지만 마이크로 미터에는 정확하지 않다는 것을 알고 있습니다.

따라서 평등을 위해 두 가지 수량을 비교할 때 원하는 의미는 "이 두 가지 수량은 각 측정에 의해 지정된 오차 막대 내에서 동일합니까?"라고 말하는 것입니다.

이제 우리는 귀하의 질문에 대한 답변이 있습니다. 당신이해야 할 일은 각 수량에 오류가 무엇인지 추적하는 것입니다. 예를 들어, 건물의 높이는 "123.56 미터의 0.01 내에"입니다. 왜냐하면 그것이 측정이 얼마나 정확한지 알고 있기 때문입니다. 그런 다음 123.5587 인 또 다른 측정을 받고 두 측정이 오류 공차 내에서 "동일"하는지 여부를 알고 싶다면 뺄셈을 수행하고 오류 공차가 발생하는지 확인하십시오. 이 경우에. 측정이 실제로 마이크로 미터에 정확한 경우, 동일하지 않습니다.

요컨대 : 당신은 현명한 오류 공차가 무엇인지 아는 유일한 사람입니다. 왜냐하면 당신은 당신이 조작하는 수치가 처음부터 어디에서 왔는지 아는 유일한 사람이기 때문입니다. 생산하는 데 사용한 장비의 정밀도가 주어지면 측정에 적합한 오류 허용 오차를 사용하십시오.

1.0에 가까운 두 개의 이중 값이 있지만 가장 유의미한 비트에서만 다르면 이들 사이의 차이는 Double.epsilon보다 큰 순서가 많습니다. 실제로, 차이는 324 크기의 크기입니다. 이것은 지수 부분의 영향 때문입니다. Double.epsilon은 거대한 음의 지수를 가지고 있으며 1.0은 지수가 0입니다 (물론 바이어스가 제거 된 후).

평등에 대한 두 가지 유사한 값을 비교하려면 비교할 값의 크기 순서 크기에 적합한 맞춤형 엡실론 값을 선택해야합니다.

비교하는 이중 값이 1.0 근처 인 경우. 그런 다음 가장 적은 비트의 값은 0.000000000000000에 가깝습니다. 당신이 비교하는 이중 값이 2 만 대에 있다면, 가장 유의미한 비트의 값은 천만큼 될 수 있습니다. 이 두 상황 모두에서 Epsilon의 단일 값은 평등 비교에 사용될 수 없습니다.

방금 켄트 보가트 아이디어를 사용 하여이 작업을 수행했습니다.

private bool IsApproximatelyEqual(double x, double y, double acceptableVariance)
{
     double variance = x > y ? x - y : y - x;
     return variance < acceptableVariance;

     //or
     //return Math.Abs(x - y) < acceptableVariance;
}

두 값이 정확히 같거나 이중 유형에 대해 가장 작은 대표적인 차이를 가지고 있다고 가정 할 때 비교에 사용될 수 있습니다. 일반적으로 말하면 double.Epsilon 두 개의 복식이 거의 동일인지 확인합니다.

.NET 프레임 워크가 같은 것을 정의하지 않는 이유

bool IsApproximatelyEqual(double value, double permittedVariance);

저를 넘어서요.

게시 한 MSDN 링크의 관련 비트는 다음과 같습니다.

그러나 엡실론 속성은 이중 유형의 일반적인 정밀도가 아닙니다. 값이 0 인 이중 인스턴스에만 적용됩니다.

참고 : Epsilon 속성의 값은 Machine Epsilon과 동일하지 않으며, 이는 부동 소수점 산술의 반올림으로 인한 상대 오차의 상한을 나타냅니다.

이 값은 X + 1.0이 1.0과 같지 않도록 가장 작은 양수 X로 정의되지 않으므로 Double.epsilon은 "거의 평등"에 사용할 수 없습니다. x + 1.0이 1.0과 같지 않도록 값이 가장 작은 값 x 인 프레임 워크에는 상수가 존재하지 않습니다.

나는 그 말을 놀라게한다. 나도 Double.epsilon이 C/C ++의 DBL_EPSILON과 동일하다고 가정했다.

내가 그 링크에 대해 읽을 수있는 것에서 '비교를 위해 괜찮은 가치를 찾아야한다'고 말하는 것 같습니다.
아마도 더 많은 지식이있는 사람은 명확하게 할 수 있습니다 :)

나는 다음을 사용합니다

public static class MathUtil {
    /// <summary>
    /// smallest such that 1.0+EpsilonF != 1.0
    /// </summary>
    public const float EpsilonF = 1.192092896e-07F;

    /// <summary>
    /// smallest such that 1.0+EpsilonD != 1.0
    /// </summary>
    public const double EpsilonD = 2.2204460492503131e-016;

    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    public static bool IsZero( this double value ) {
        return value < EpsilonD && value > -EpsilonD;
    }

    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    public static int Sign( this double value ) {
        if ( value < -EpsilonD ) {
            return -1;
        }
        if ( value > EpsilonD )
            return 1;
        return 0;
    }

그리고 두 개의 복식 'a'와 'b'의 평등을 확인하려면 사용할 수 있습니다.

(a-b).IsZero();

비교 결과를 얻으려면 사용하십시오.

(a-b).Sign();

복식을 비교하는 데있어 문제는 동일하지만 반올림 오류로 인해 동일한 값으로 평가하지 않는 두 가지 다른 수학 결과를 비교할 때 엡실론보다 큰 차이가 있다는 것입니다. 가장자리 케이스를 제외하고. 신뢰할 수있는 엡실론 가치를 사용하는 것도 어렵습니다. 일부 사람들은 정적 최소 차이를 사용하면 이중 자체가 높거나 낮을 때 차이가 너무 작거나 크다는 것을 의미 할 수 있기 때문에 일부 사람들은 두 배의 차이가 비율 값보다 낮 으면 값이 비율이면 동일하다고 생각합니다.

Silverlight Control Toolkit 내에 두 번 포함 된 코드는 다음과 같습니다.

    public static bool AreClose(double value1, double value2)
    {
        //in case they are Infinities (then epsilon check does not work)
        if(value1 == value2) return true;
        // This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON
        double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON;
        double delta = value1 - value2;
        return(-eps < delta) && (eps > delta);
    }

그들이 사용하는 한 곳에서 1e-6 Epsilon의 경우; 다른 사람으로 그들은 사용합니다 1.192093E-07. 자신의 엡실론을 선택하고 싶을 것입니다.

직접 계산하거나 자신의 상수를 정의 해야하는 선택은 없습니다.

double calculateMachineEpsilon() {
    double result = 1.0;
    double one = 1.0/256;

    while(one + result/2.0 != 1.0) {
        result/=2.0;
    }
    return result;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top