Double.Epsilon per l'uguaglianza, superiore, inferiore, minore o uguale, maggiore o uguale a

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

  •  18-09-2019
  •  | 
  •  

Domanda

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

  

Se si crea un algoritmo personalizzato   determina se due virgola mobile   numeri possono essere considerati uguali, si   deve utilizzare un valore che è maggiore di   Epsilon costante per stabilire la   accettabile margine di assoluta   differenza per i due valori sia   considerati uguali. (In genere, che   margine di differenza è molte volte   maggiore di Epsilon.)

Quindi, è questo non è davvero un epsilon che potrebbe essere utilizzato per i confronti? Io non capisco la formulazione di MSDN.

Può essere utilizzato come Epsilon negli esempi qui? - Qual è il modo più efficace per float e double confronto ?

E infine questo sembra davvero importante quindi mi piacerebbe essere sicuro di avere una solida implementazione per l'uguaglianza, maggiore di, minore di, minore o uguale a, e maggiore o uguale a.

È stato utile?

Soluzione

Non so cosa fumavano quando hanno scritto che. Double.Epsilon è il valore più piccolo rappresentabile non denormal virgola mobile che non è 0. Tutto quello che sai è che, se c'è un errore di troncamento, sarà sempre più di questo valore. Molto più grande.

Il tipo System.Double può rappresentare valori precisi per un massimo di 15 cifre. Così una semplice prima stima ordine se un valore doppio x è uguale ad una costante è di usare un epsilon costante * 1E-15

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;
}

È necessario fare attenzione, però, errori di troncamento possono accumulare. Se entrambi x e y vengono calcolati i valori, allora si deve aumentare l'epsilon.

Altri suggerimenti

  

Mi piacerebbe essere sicuro di avere una solida implementazione per l'uguaglianza, maggiore di, minore di, minore o uguale a, e maggiore o uguale a.

Si utilizza binario aritmetica in virgola mobile.

binario aritmetica in virgola mobile è stato progettato per rappresentare quantità fisiche come lunghezza, massa, carica, tempo, ecc.

Presumibilmente quindi si utilizza binario aritmetica in virgola mobile come è stato destinato ad essere utilizzato:. Fare l'aritmetica sulle grandezze fisiche

misure di grandezze fisiche hanno sempre una particolare precisione, a seconda della precisione del dispositivo utilizzato per misurare loro.

Dal momento che tu sei quella che fornisce i valori per le quantità che si sta manipolando, tu sei quello che sa che cosa le "barre di errore" sono su quella quantità. Ad esempio, se si sta fornendo la quantità "l'altezza dell'edificio è 123.56 metri" poi si sa che questo è preciso al centimetro, ma non al micrometro.

Pertanto, quando si confrontano due quantità per l'uguaglianza, la semantica desiderati a dire "sono queste due quantità uguali all'interno delle barre di errore specificati per ogni misurazione?"

Così ora abbiamo una risposta alla tua domanda. Che cosa si deve fare è tenere traccia di ciò che l'errore è su ogni quantità; per esempio, l'altezza dell'edificio è "entro 0.01 di 123.56 metri", perché si sa che è come precisa la misura è. Se poi si ottiene un altro la misura che è 123,5587 e volete sapere se le due misure sono "uguali" entro le tolleranze di errore, poi fare la sottrazione e vedere se cade nella tolleranza di errore. In questo caso lo fa. Se le misure sono state, infatti, precisa al micrometro, allora non sono uguali.

In breve: sei l'unica persona qui che sa cosa tolleranze sensibili sono, perché sei l'unica persona che sa dove le figure si stanno manipolando provenivano da in primo luogo. Utilizzare qualsiasi tolleranza di errore ha senso per le vostre misure dato la precisione dell'apparecchiatura utilizzata per produrlo.

Se si dispone di due valori doppi che sono vicino a 1,0, ma differiscono per solo i loro bit meno significativi, quindi la differenza tra loro saranno molti ordini di grandezza maggiore di Double.Epsilon. In effetti, la differenza è 324 ordini decimali di grandezza. Questo perché l'effetto della porzione esponente. Double.Epsilon ha un enorme esponente negativo su di esso, mentre 1.0 ha un esponente pari a zero (dopo i pregiudizi vengono rimossi, naturalmente).

Se si desidera confrontare due valori simili per l'uguaglianza, allora si avrà bisogno per scegliere un valore epsilon personalizzato che è appropriato per la dimensione degli ordini di grandezza dei valori da confrontare.

Se i valori doppi che si sta confrontando sono vicino 1.0. Quindi il valore del bit meno siginificant sarebbe quasi 0,0000000000000001. Se i valori doppi che si stanno confrontando sono nelle quadrilioni, allora il valore del bit meno significativo potrebbe essere fino a un migliaio. Nessun valore unico per epsilon potrebbe essere utilizzato per i confronti di uguaglianza in entrambe le circostanze.

Ho appena fatto questo -. Usando Kent Bogarts idea

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;
}

Potrebbe essere usato per i confronti, supponendo che si vuole garantire i due valori sono o esattamente uguale, o che hanno la più piccola differenza rappresentabile per il tipo double. In generale, si consiglia di utilizzare un numero maggiore di double.Epsilon per verificare se due doppie sono approssimativamente uguali.

Perché il framework .NET non definisce qualcosa come

bool IsApproximatelyEqual(double value, double permittedVariance);

è oltre me.

Credo che i bit pertinenti nel link che hai postato MSDN sono queste:

  

Tuttavia, la proprietà non è un Epsilon   misura generale di precisione della   tipo Double; si applica solo a doppio   le istanze che hanno un valore pari a zero.

     

Nota: Il valore della Epsilon   proprietà non è equivalente alla macchina   epsilon, che rappresenta la tomaia   vincolato dell'errore relativo dovuto   arrotondamento in virgola mobile.

     

Questo valore non è definito come il più piccolo   numero x positivo, tale che x + 1.0   è diverso da 1.0, Double.Epsilon   non può essere utilizzato per "quasi uguaglianza".   Non esiste costante nel   quadro il cui valore è il più piccolo   numero x positivo, tale che x + 1.0   non è uguale a 1,0.

Devo dire, che mi sorprende. Anch'io dato per scontato che Double.Epsilon era l'equivalente di DBL_EPSILON in C / C ++ - chiaramente non!

Da quello che posso leggere di tale collegamento, sembra voler dire 'avete bisogno di capire un discreto rapporto te stesso per il confronto', che è piuttosto sorprendente per non dire altro.
Forse qualcuno più informato può chiarire:)

Io uso il seguente

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;
    }

e se si desidera controllare per l'uguaglianza di due doppie 'a' e 'b', è possibile utilizzare

(a-b).IsZero();

e se si vuole ottenere il risultato del confronto, utilizzare

(a-b).Sign();

Il problema con il confronto doppie è che quando si fa un confronto tra due diversi risultati di matematica che sono uguali, ma che, a causa di errori di arrotondamento, non valutando allo stesso valore, avranno qualche differenza ... che è più grande di Epsilon, tranne casi limite. E l'utilizzo di un valore epsilon affidabile è anche difficile. Alcune persone considerano due doppie uguali se la differenza tra loro è minore di un certo valore percentuale, dal momento che utilizza un epsilon differenza minima statica può indicare che la differenze sono troppo piccole o grandi quando il doppio se è alto o basso.

Ecco un po 'di codice che ha incluso due volte entro il Control Toolkit Silverlight:

    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);
    }

In un luogo che usano 1e-6 per Epsilon; in un altro usano 1.192093E-07. Si vuole scegliere il proprio epsilon.

Non c'è scelta si deve calcolare da soli o definire proprio costante.

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

    while(one + result/2.0 != 1.0) {
        result/=2.0;
    }
    return result;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top