2013-04-08 12 views
5

Ich habe die folgenden Berechnungen in Excel, die ich in einer gespeicherten Prozedur verwenden möchten.SQL-Fließkomma-Genauigkeit begrenzt auf 6 Ziffern

Excel

CellA: 45/448.2 = 0.100401606425703 
CellB: 1-CellA = 0.899598393574297 
CellC: 1-CellB = 0.100401606425703 
CellD: CellC * 448.2 = 45.000000000000000 

In SQL mache ich folgendes:

declare @a decimal(18,15) = 45/448.2 
declare @b decimal(18,15) = [email protected] 
declare @c decimal(18,15) = [email protected] 
declare @d decimal(18,15) = @c * 448.2 

ich auch die Berechnung in einer Zeile versucht haben, laufen

declare @e decimal(18,15) = (1-(1-(45/448.2)))*448.2 

, wenn ich die Werte SQL zurückgeben gibt mir folgendes:

@a: 0.100401000000000 
@b: 0.899599000000000 
@c: 0.100401000000000 
@d: 44.999728200000000 

@e: 44.999728200000000 

Ich habe versucht, die Genauigkeit der Dezimalstellen in SQL anzupassen, aber ich nichts macht einen Unterschied, es gibt nur die ersten 6 Stellen der Dezimalstelle zurück.

Führt Excel beim Ausführen der Formel eine Optimierung durch?

Irgendwelche Ideen?

+0

Versuchen, sagen wir, SELECT 45/CAST (448,2 AS DECIMAL (18,1)) '. [Die Links hier] (http://stackoverflow.com/a/5385417/73226) sagen Ihnen die Regeln für den resultierenden Datentyp der Division. –

+0

@MartinSmith das gibt mir eine vollständigere Dezimalstelle für @a, obwohl meine Antwort 45.000000000000085 ist, können Sie erklären, warum? – ScampDoodle

+0

Es wird in den zwei Links von der vorherigen Antwort erklärt, die ich zu faul war, um oben zu reproduzieren. "e1/e2 ergibt p = p1 - s1 + s2 + max (6, s1 + p2 + 1), s = max (6, s1 + p2 + 1)". Wenn 'p'' '38' wäre, dann' s' ist abgeschnitten bei '6' –

Antwort

7

Auch nur Ihre erste Linie ist genug, um das Problem zu zeigen:

declare @a decimal(18,15) = 45/448.2 
print @a 

gibt

--------------------------------------- 
0.100401000000000 

Dies, weil der Datentypen ist. Wenn Sie sagen,

448.2 

es ist (pro the documentation) als Konstante vom Typ interpretiert decimal und also per the documentation,

In Transact-SQL-Anweisungen, eine Konstante mit Dezimalpunkt automatisch konvertiert in einen numerischen Datenwert, unter Verwendung der mindestens erforderlichen Genauigkeit und Skalierung. Zum Beispiel ist die Konstante 12.345 in einen numerischen Wert mit einer Genauigkeit von 5 und einer Skala von umgewandelt 3.

So 448.2 ist decimal(4,3). 45 ist integer, die in Kombination mit einem decimalis treated as having precision of 10 and scale 0. Wenn wir teilen, sagen the rules

Operation  Result precision      Result scale 
e1/e2  p1 - s1 + s2 + max(6, s1 + p2 + 1)  max(6, s1 + p2 + 1) 

die in diesem Fall eine Ergebnisgenauigkeit von 10 - 3 + 0 + max(6, 0 + 3 + 1) und Skala von max(6, 0 + 3 + 1) gibt, die aus zu 13 und 6 kommt.

Die Ergebnisskala von 6 ist, warum das Ergebnis nur diese sechs Dezimalstellen hat.

Der Weg, es zu beheben, besteht darin, Ihre Operanden in einen geeigneten Typ zu bringen, bevor Sie auf ihnen reagieren; zum Beispiel sind hier zwei Möglichkeiten:

eine Reihe Zwingen als Gleitkommazahlen behandelt werden:

declare @a decimal(18,15) = 45/448.2e0 
select @a 

--------------------------------------- 
0.100401606425703 

Explizit eine Dezimalskala liefern:

declare @a decimal(18,15) = 45/cast(448.2 as decimal(18,10)) 
select @a 

--------------------------------------- 
0.100401606425703 
+0

Das hat mich auf den richtigen Weg gebracht, ich musste anpassen wie viele Dezimalstellen, aber letztendlich war das die richtige Antwort – ScampDoodle