2016-05-08 11 views
0

Für die Randwertanalyse im Test habe ich versucht, die kleinsten Schrittgrößen für Double oder Floats in .NET zu erhalten. Dies ermöglicht es mir, den nächsten größeren und nächstkleineren Wert zu erhalten, der in einem Double oder Float dargestellt werden kann.Erhalten der kleinsten Schrittgröße für ein (nicht Null) Doppel oder Float

double.epsilon, "gilt nur für Double-Instanzen, die einen Wert von Null oder einen Exponenten von -1022 haben".

Nehmen wir an, ich habe ein beliebiges Double oder Float. Was ist der nächste größere und nächstkleinere Wert, den ich in .Net darstellen kann?

auf dem MSDN-Artikel Basierend habe ich den folgenden Code implementiert, das plausibel aussieht:

private static int GetExponentWithMinorAdjustment(double value) 
{ 
    //int indent = result.Length; 

    // Convert the double to an 8-byte array. 
    byte[] bytes = BitConverter.GetBytes(value); 

    int exponent = (bytes[7] & 0x07F) << 4; 
    exponent = exponent | ((bytes[6] & 0xF0) >> 4); 
    int adjustment = exponent != 0 ? 1023 : 1022; 

    return exponent != 0 ? exponent - 1 : exponent; ; 
} 

private static double NextLargerNumber(double value) 
{ 
    // Cannot use double.epsilon * Math.Pow(2, GetExponentWithMinorAdjustment(value)) as this results in infinity 
    return value + Math.Pow(2, GetExponentWithMinorAdjustment(value) - 1074)); 
} 

Das Problem mit dem obigen Code ist, dass es wackelig aussieht. Beachten Sie den ternären Operator (inspiriert von dem MSDN-Artikel); Was ist der Zweck dieser Anpassung?

Auch während der Ausgang von mehreren Tests OK für positive Doppel Werte sieht, scheinen die Ergebnisse für negative Werte nicht so gut (Ausgabebild sehen): Program Output

Was wäre eine akzeptable, richtige und ideale Lösung zu diesem Problem aussehen?

Antwort

1

Verwenden Sie unsicheren Code, um die Bits direkt einem unsigned int zuzuordnen, inkrementieren oder dekrementieren, zurück konvertieren.

Möglicherweise erfordern zusätzliche spezielle Handhabung an den Grenzen von 0 und die speziellen Werte für Unendlichkeit, Nan und so weiter.

+0

Danke - gibt es eine Möglichkeit, auch die Schrittgröße durch dieses Inkrement dargestellt zu erhalten? – Andrew

+0

im Falle eines float zumindest (ich denke, Doppelgänger verhalten sich auch auf die gleiche Weise) es ist variabel in Abhängigkeit von der Genauigkeit der Zahl (wie viel von dem Wert auf der rechten Seite der Dezimalstelle verwendet wird), alles, was Sie tun können, ist nimm die zwei Werte und erhalte den Unterschied zwischen ihnen in verschiedenen Präzisionsstufen – War

+0

Gute Punkte. Es ist interessant festzustellen, dass der ursprünglich vorgeschlagene Code für die obigen Beispiele dieselben Ergebnisse liefert wie die in der Antwort vorgeschlagene Inkrementtechnik. – Andrew