Die SQL Server-Dezimaloperation ist nicht genau
Wenn ich diese einfache Operation in SQL Server ausführe:
Select 800.0 /30.0
Ich erhalte den Wert 26.666666, wobei selbst wenn er 6-stellig ist, er 26.666667 sein sollte. Wie kann ich die Berechnung genau machen? Ich habe versucht, online danach zu suchen, und eine Lösung gefunden, bei der ich jeden Operanden vor der Operation auf eine hochpräzise Dezimalstelle umwandelte. Dies ist jedoch für mich nicht praktisch, da ich viele lange komplexe Berechnungen habe. Ich denke, es muss eine bessere Lösung geben.
Antworten
Bei einer Verwendungsteilung werden in SQL Server alle Ziffern nach der resultierenden Skalierung abgeschnitten und nicht gerundet. Für Ihren Ausdruck haben Sie ein decimal(4,1)und ein decimal(3,1), was zu einem führt decimal(10,6):
Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Scale = max(6, s1 + p2 + 1)
Infolgedessen 26.66666666666666~wird auf abgeschnitten 26.666666.
Sie können dies umgehen, indem Sie die Genauigkeit und Skalierung erhöhen und dann CONVERTzu der erforderlichen Präzision und Skalierung zurückkehren. Erhöhen Sie beispielsweise die Genauigkeit und Skalierung von decimal(3,1)to decimal(5,2)und konvertieren Sie zurück in a decimal(10,6):
SELECT CONVERT(decimal(10,6),800.0 / CONVERT(decimal(5,3),30.0));
Dies kehrt zurück 26.666667.
Dies könnte hilfreich sein:
Verwenden Sie ROUND (Transact-SQL)
SELECT ROUND(800.0 /30.0, 5) AS RoundValue;
Ergebnis:
RoundValue
26.666670
Ich glaube, das liegt daran, dass SQL Server Ihre Zahlen als decimalWerte verwendet (die genau sind, z. B. 6.6666 und 6.6667, bedeutet genau diese Werte, nicht 6 und zwei Drittel) und nicht als floatWerte (die mit ungefähren Zahlen arbeiten können).
Wenn Sie es zu floatBeginn explizit in a umwandeln , sollten Sie Ihre Berechnungen reibungslos ausführen.
Hier einige Beispiele , die die Differenz zwischen zu demonstrieren int, decimalund floatBerechnungen
- Teilen Sie 20 durch 3
- Teilen Sie 20 durch 3 und multiplizieren Sie dann erneut mit 3 (was mathematisch 20 sein sollte).
SELECT (20/3) AS int_calc,
(20/3) * 3 AS int_calc_x3,
(CAST(20 AS decimal(10,3)) /3) AS dec_calc,
(CAST(20 AS decimal(10,3)) /3) * 3 AS dec_calc_x3,
(CAST(20 AS float) /3) AS float_calc,
(CAST(20 AS float) /3) * 3 AS float_calc_x3
mit den folgenden Ergebnissen
int_calc int_calc_x3 dec_calc dec_calc_x3 float_calc float_calc_x3
6 18 6.666666 19.999998 6.66666666666667 20
In Ihrem Fall können Sie verwenden
Select CAST(800.0 AS float) /30.0
was zu 26.6666666666667 führt
Beachten Sie, wenn Sie dann mit 30 multiplizieren, erhalten Sie das richtige Ergebnis, z.
Select (CAST(800.0 AS float) /30.0) * 30
ergibt 800. Lösungen, die sich mit Dezimalstellen befassen, haben dies nicht.
Beachten Sie auch, dass, sobald Sie es als Float haben, es ein Float bleiben sollte, bis es wieder in eine Dezimalzahl oder ein Int konvertiert wird (z. B. in einer Tabelle als Int gespeichert). Damit...
SELECT A.Num / 30
FROM (Select ((CAST(800.0 AS float) /30.0) * 30) AS Num) AS A
wird immer noch zu 26.6666666666667 führen
Dies wird Ihnen hoffentlich bei Ihren langen komplexen Berechnungen helfen.