8 Stimmen

Wie kann man die Genauigkeit und Skalierung eines numerischen Wertes effizient überprüfen?

Ich schreibe eine Routine, die Daten vor dem Einfügen in eine Datenbank validiert, und einer der Schritte ist zu sehen, wenn numerische Werte die Präzision und Skala eines Numeric(x,y) SQL-Server-Typs passen.

Ich habe die Präzision und Skala von SQL-Server bereits, aber was ist der effizienteste Weg in C#, um die Präzision und Skala eines CLR-Wertes zu erhalten, oder zumindest zu testen, ob es eine bestimmte Einschränkung passt?

Im Moment konvertiere ich den CLR-Wert in eine Zeichenkette und suche dann mit .IndexOf() nach der Position des Dezimalpunkts. Gibt es einen schnelleren Weg?

13voto

Jimmy Punkte 85199
System.Data.SqlTypes.SqlDecimal.ConvertToPrecScale( new SqlDecimal (1234.56789), 8, 2)

ergibt 1234,57. Es werden zusätzliche Ziffern nach dem Komma abgeschnitten, und es wird ein Fehler ausgegeben, anstatt zu versuchen, Ziffern vor dem Komma abzuschneiden (z. B. ConvertToPrecScale(12344234, 5,2)

0 Stimmen

1234,57, aber ich habe dich trotzdem gewählt, weil es eine tolle Antwort ist.

5voto

Craig Punkte 6529

Ohne eine Ausnahme auszulösen, können Sie die folgende Methode verwenden, um festzustellen, ob der Wert den Präzisions- und Skalenbeschränkungen entspricht.

private static bool IsValid(decimal value, byte precision, byte scale)
{
    var sqlDecimal = new SqlDecimal(value);

    var actualDigitsToLeftOfDecimal = sqlDecimal.Precision - sqlDecimal.Scale;

    var allowedDigitsToLeftOfDecimal = precision - scale;

    return 
        actualDigitsToLeftOfDecimal <= allowedDigitsToLeftOfDecimal && 
        sqlDecimal.Scale <= scale;
}

3voto

Evil Pigeon Punkte 1712

Hier ist ein mathematischer Ansatz.

private static bool IsValidSqlDecimal(decimal value, int precision, int scale)
{
    var minOverflowValue = (decimal)Math.Pow(10, precision - scale) - (decimal)Math.Pow(10, -scale) / 2;
    return Math.Abs(value) < minOverflowValue;
}

Dies berücksichtigt, wie Sql-Server tun Rundung und verhindern Überlauf Fehler, auch wenn wir die Genauigkeit überschreiten. Zum Beispiel:

DECLARE @value decimal(10,2)
SET @value = 99999999.99499 -- Works
SET @value = 99999999.995   -- Error

0voto

HasaniH Punkte 7873

Sie können decimal.Truncate(val) verwenden, um den ganzzahligen Teil des Wertes zu erhalten, und decimal.Remainder(val, 1), um den Teil nach dem Dezimalpunkt zu erhalten, und dann prüfen, ob jeder Teil Ihre Einschränkungen erfüllt (ich nehme an, dies kann eine einfache > oder < Prüfung sein)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X