Frage

Update

OK, nach einigen Untersuchungen, und Dank im großen Teil auf die hilfreichen Antworten von Jon zur Verfügung gestellt und Hans, das ist, was ich in der Lage war, zusammen zu stellen. Bisher ich denke, es scheint gut zu funktionieren. Ich würde wetten, mein Leben nicht auf seiner Gesamt Richtigkeit, natürlich.

public static int GetSignificantDigitCount(this decimal value)
{
    /* So, the decimal type is basically represented as a fraction of two
     * integers: a numerator that can be anything, and a denominator that is 
     * some power of 10.
     * 
     * For example, the following numbers are represented by
     * the corresponding fractions:
     * 
     * VALUE    NUMERATOR   DENOMINATOR
     * 1        1           1
     * 1.0      10          10
     * 1.012    1012        1000
     * 0.04     4           100
     * 12.01    1201        100
     * 
     * So basically, if the magnitude is greater than or equal to one,
     * the number of digits is the number of digits in the numerator.
     * If it's less than one, the number of digits is the number of digits
     * in the denominator.
     */

    int[] bits = decimal.GetBits(value);

    if (value >= 1M || value <= -1M)
    {
        int highPart = bits[2];
        int middlePart = bits[1];
        int lowPart = bits[0];

        decimal num = new decimal(lowPart, middlePart, highPart, false, 0);

        int exponent = (int)Math.Ceiling(Math.Log10((double)num));

        return exponent;
    }
    else
    {
        int scalePart = bits[3];

        // Accoring to MSDN, the exponent is represented by
        // bits 16-23 (the 2nd word):
        // http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx
        int exponent = (scalePart & 0x00FF0000) >> 16;

        return exponent + 1;
    }
}

Ich habe es nicht so gründlich getestet. Hier sind ein paar Beispiel-Ein- / Ausgänge, aber:

Value          Precision
0              1 digit(s).
0.000          4 digit(s).
1.23           3 digit(s).
12.324         5 digit(s).
1.2300         5 digit(s).
-5             1 digit(s).
-5.01          3 digit(s).
-0.012         4 digit(s).
-0.100         4 digit(s).
0.0            2 digit(s).
10443.31       7 digit(s).
-130.340       6 digit(s).
-80.8000       6 digit(s).

Sie diesen Code verwenden, ich denke, ich würde mein Ziel erreichen durch so etwas wie dies zu tun:

public static decimal DivideUsingLesserPrecision(decimal x, decimal y)
{
    int xDigitCount = x.GetSignificantDigitCount();
    int yDigitCount = y.GetSignificantDigitCount();

    int lesserPrecision = System.Math.Min(xDigitCount, yDigitCount);

    return System.Math.Round(x / y, lesserPrecision);
}

Ich habe nicht wirklich fertig, durch diese Arbeit, though. Jeder, der auf Aktien Gedanken will: so viel geschätzt würde


Original Question

Angenommen, ich habe diesen Code schreiben:

decimal a = 1.23M;
decimal b = 1.23000M;

Console.WriteLine(a);
Console.WriteLine(b);

Die oben gezeigten Wille Ausgabe:

1.23
1.23000

Ich finde, dass dies funktioniert auch, wenn ich decimal.Parse("1.23") für a und decimal.Parse("1.23000") für b verwenden (was bedeutet, diese Frage auf Fälle anwendbar ist, wenn das Programm eine Benutzereingabe empfängt).

So eindeutig ein decimal Wert ist irgendwie „bewusst“, was ich werde seine Genauigkeit . Ich sehe jedoch keine Mitglieder auf der decimal Typ, der jede mögliche Weise den Zugriff auf diese bieten, abgesehen von ToString selbst.

Angenommen, ich wollte zwei decimal Werte multiplizieren und das Ergebnis an die Präzision des ungenauen Arguments trimmen. Mit anderen Worten:

decimal a = 123.4M;
decimal b = 5.6789M;

decimal x = a / b;

Console.WriteLine(x);

Die obigen Ausgänge:

21.729560302171195125816619416

Was ich frage ist: Wie kann ich eine Methode schreiben, die 21.73 statt zurückkehren würde (da 123.4M vier signifikante Ziffern hat)

Um klar zu sein: Ich weiß, ich ToString auf beiden Argumenten nennen könnte, die signifikanten Zahlen in jeder Kette zählen und diese Zahl verwenden, um das Ergebnis der Berechnung runden. Ich suche ein andere Art und Weise, wenn möglich.

(I auch erkennt, dass in den meisten Szenarien, in denen man es zu tun mit signifikanten Zahlen, brauchen Sie vermutlich nicht den decimal Typen verwendet werden. Aber ich frage, weil, wie ich bereits erwähnt am Anfang, der decimal Typ erscheint enthält Informationen über Präzision, während double nicht, soweit ich weiß.)

War es hilfreich?

Lösung

Sie können mit Decimal.GetBits die bekommen Rohdaten und Arbeit es aus, dass.

Leider habe ich keine Zeit zu schreiben Beispielcode zur Zeit - und Sie wollen wahrscheinlich zu verwenden

Andere Tipps

Die Lösung oben fällt aus dem Bett schnell mit Werten wie 1200, in dem die Anzahl der signifikanten Ziffern 2, aber die Funktion zurückkehrt 4. Vielleicht gibt eine konsistente Art und Weise ist mit einer solchen Situation zu umgehen dh zu überprüfen, um sicher Rückgabewert machen nicht funktioniert umfassen Nullen in dem ganzzahligen Anteil ohne einen Bruchteil nachlauf.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top