Double.Epsilon für Gleichheit, größer als, kleiner als, kleiner als oder gleich, größer als oder gleich

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

  •  18-09-2019
  •  | 
  •  

Frage

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

  

Wenn Sie einen benutzerdefinierten Algorithmus erstellen, die   bestimmt, ob zwei Gleitkommazahlen   Zahlen können als gleich betrachtet werden, Sie   muss einen Wert verwenden, der größer ist als   Epsilon die Konstante der etablieren   akzeptabler absolute Marge von   Differenz für die beiden Werte zu sein,   als gleich betrachtet. (In der Regel, dass   Spielraum der Differenz ist oft   größer als Epsilon).

Das ist also nicht wirklich ein Epsilon, die für Vergleiche verwendet werden könnte? Ich verstehe nicht wirklich in der MSDN-Formulierung.

Kann es als epsilon in den Beispielen hier verwendet werden? - Was ist der effektivste Weg für Schwimmer und Doppel Vergleich ?

Und schließlich scheint dies wirklich wichtig, so würde Ich mag, um sicherzustellen, ich habe eine solide Umsetzung für Gleichheit, größer als, kleiner als, kleiner als oder gleich und größer als oder gleich.

War es hilfreich?

Lösung

Ich weiß nicht, was sie raucht, wenn sie das schreibt. Double.Epsilon ist der kleinste darstellbare nicht-denormal Gleitkomma-Wert, der nicht 0 Alles, was Sie wissen, ist, dass, wenn es ein Rundungsfehler ist, wird es immer sein, größer als dieser Wert. Viel größer.

Der System.Double Typ Werte genau bis zu 15 Ziffern stellen kann. So eine einfache Abschätzung erste Ordnung, wenn ein doppelter Wert x auf eine Konstante gleich ist ein Epsilon von konstant zu verwenden * 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;
}

Sie haben allerdings aufpassen, können Rundungsfehler akkumulieren. Wenn beide x und y Werte berechnet werden, dann müssen Sie das epsilon erhöhen.

Andere Tipps

  

Ich möchte sicherstellen, dass ich eine solide Umsetzung für Gleichheit, größer als, kleiner als, kleiner als oder gleich und größer als oder gleich.

Sie verwenden binäre Gleitkomma-Arithmetik.

Binary Gleitkomma-Arithmetik wurde entwickelt, um physikalische Größen wie Länge, Masse, Ladung, Zeit darstellen, und so weiter.

Vermutlich dann binäre Gleitpunktarithmetik Sie verwenden, wie es beabsichtigt war, verwendet zu werden. Arithmetik auf physikalische Größen zu tun

Die Messungen physikalischer Größen immer eine besondere Präzision aufweisen, abhängig von der Genauigkeit des Geräts verwendet, um sie zu messen.

Da Sie die eine Bereitstellung der Werte für die Mengen sind Sie manipulieren, sind Sie derjenige, der weiß, was die „Fehlerbalken“ auf dieser Menge sind. Wenn Sie die Menge zum Beispiel bieten „die Höhe des Gebäudes ist 123,56 Meter“, dann wissen Sie, dass dies auf den Zentimeter genau ist, aber nicht auf den Mikrometer.

Wenn daher zwei Größen für die Gleichstellung zu vergleichen, ist die gewünschte Semantik zu sagen, „sind diese beiden Größen gleich innerhalb der Fehlerbalken nach jeder Messung festgelegt?“

So, jetzt haben wir eine Antwort auf Ihre Frage. Was Sie tun müssen, ist im Auge behalten, was der Fehler auf jede Menge ist; zum Beispiel ist die Höhe des Gebäudes „innerhalb von 0,01 von 123,56 Metern“, weil Sie wissen, das ist, wie präzise die Messung. Wenn Sie dann eine weitere Messung erhalten, die 123.5587 und wollen wissen, ob die beiden Messungen „gleich“ innerhalb der Fehlertoleranzen sind, haben dann die Subtraktion und sehen, ob es in die Fehlertoleranz fällt. In diesem Fall ist es der Fall ist. Wenn die Messungen an den Mikrometer in der Tat präzise waren, dann sind sie nicht gleich.

Kurz gesagt: Sie sind der einzige Mensch hier, der weiß, was vernünftige Fehlertoleranzen sind, weil Sie die einzige Person sind, der weiß, wo die Zahlen Sie an erster Stelle kamen manipulieren. Verwenden Sie, was die Fehlertoleranz Sinn für Ihre Messungen gegeben, um die Genauigkeit der Geräte macht Sie verwendet es zu produzieren.

Wenn Sie zwei doppelte Werte haben, die nahe bei 1,0 liegen, aber sie unterscheiden sich nur in ihrer am wenigsten signifikanten Bits, dann wird der Unterschied zwischen ihnen werden viele Größenordnungen größer sein als Double.Epsilon. In der Tat ist die Differenz 324 dezimal Größenordnung. Dies ist wegen der Wirkung des Exponenten Teil. Double.Epsilon hat einen großen negativen Exponenten auf sich, während 1,0 einen Exponenten von Null hat (nachdem die Verzerrungen entfernt werden, natürlich).

Wenn Sie zwei Ähnliche Werte für die Gleichstellung vergleichen wollen, dann müssen Sie einen benutzerdefinierten Epsilon-Wert wählen, die für die Aufträge-of-Größe Größe der Werte geeignet ist, verglichen werden.

Wenn die doppelten Werte, die Sie vergleichen sind in der Nähe von 1,0. Dann wird der Wert des am wenigsten siginificant Bit würde in der Nähe von ,0000000000000001 sein. Wenn die doppelten Werte, die Sie in den Trillionen vergleichen, dann wird der Wert des niedrigstwertigen Bits könnte so viel wie tausend sein. Kein einziger Wert für epsilon für Gleichheit Vergleiche in diesen beiden Umständen verwendet werden könnte.

Ich habe gerade das. - mit Kent Bogarts Idee

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

Es könnte für Vergleiche verwendet werden, vorausgesetzt, Sie sind den kleinsten darstellbaren Unterschied für den Doppeltyp der beiden Werte sind entweder genau gleich, oder müssen sicherstellen wollen. Im Allgemeinen würden Sie eine Zahl größer als double.Epsilon verwenden möchten, zu überprüfen, ob zwei Doppelzimmer sind etwa gleich groß.

Warum das .NET Framework wird nicht definiert, so etwas wie

bool IsApproximatelyEqual(double value, double permittedVariance);

ist mir schleierhaft.

Ich denke, die einschlägigen Bits in dem MSDN-Link Sie auf dem Laufenden sind diese:

  

Allerdings ist die Epsilon-Eigenschaft nicht   allgemeines Maß für Präzision der   Doppel-Typ; es gilt nur für Doppel   Instanzen, die einen Wert von Null haben.

     

Hinweis: Der Wert des Epsilon   Eigenschaft ist nicht gleichbedeutend mit Maschinen   epsilon, die den oberen darstellt   gebunden des relativen Fehlers aufgrund   Abrunden in Gleitkommaarithmetik.

     

Dieser Wert wird nicht als kleinstes definiert   positive Zahl x, so daß x + 1,0   nicht gleich 1,0 ist, so Double.Epsilon   kann nicht für „fast Gleichheit“ verwendet werden.   Es existiert keine Konstante in der   Rahmen, dessen Wert kleinsten   positive Zahl x, so daß x + 1,0   nicht gleich 1,0 ist.

Ich muss sagen, dass mich überrascht. Auch ich hatte angenommen, dass Double.Epsilon das Äquivalent von DBL_EPSILON in C / C ++ war - eindeutig nicht!

Von dem, was ich von diesem Link lesen kann, es scheint zu sagen, ‚Sie müssen einen anständigen Wert selbst, um herauszufinden, für Vergleiche‘, die eher überraschend ist, gelinde gesagt.
Vielleicht hat jemand mehr knowledgable kann klären:)

Ich verwende die folgende

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

und wenn Sie wollen für die Gleichstellung von zwei Doppelzimmer ‚a‘ und ‚b‘ überprüfen, können Sie

(a-b).IsZero();

, und wenn Sie das Vergleichsergebnis erhalten möchten, verwenden Sie

(a-b).Sign();

Das Problem mit Doppel Vergleich ist, dass, wenn Sie einen Vergleich zwischen zwei verschiedenen mathematischen Ergebnissen tun, die gleich sind, aber aufgrund Fehler von Rundungen sind nicht auf den gleichen Wert bewertet, werden sie einen Unterschied ... haben was größer als epsilon, außer Rand Fällen. Und einen zuverlässigen Epsilon-Wert verwendet, ist ebenfalls schwierig. Manche Leute halten zwei Doppelzimmer gleich, wenn der Unterschied zwischen ihnen kleiner als ein Prozentwert, da ein statisches minimale Differenz epsilon verwenden, können Sie Ihre Unterschiede bedeuten, sind zu klein oder groß, wenn die Doppel selbst hoch oder niedrig ist.

Hier ist ein Code, der zweimal in der Silverlight Control Toolkit enthalten:

    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 einem Ort, der sie 1e-6 für Epsilon verwenden; in einem anderen verwenden sie 1.192093E-07. Sie wollen Ihr eigenes epsilon wählen.

Es gibt keine andere Wahl haben Sie es selbst berechnen oder eigene Konstante definiert werden.

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

    while(one + result/2.0 != 1.0) {
        result/=2.0;
    }
    return result;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top