2017-04-10 12 views
0

Ich lese ein Fließkommafeld in ein C# -Doppelfeld. Der DB-Wert 0,1 wird als 0.10000000149011612 gelesen. Ich finde das merkwürdig, da die Antworten dieser Frage darauf eingehen, dass FLOAT 8 Bytes verwendet, was sicher genug ist für 0,1?SqlServer kann 0.1 nicht genau in einem FLOAT-Feld speichern?

SQL Server verwendet entweder 4 Bytes oder 8 Bytes, um nicht-dezimale Gleitkommazahlen zu speichern.

Wenn Sie echte oder einen beliebigen Wert im Bereich Float < 1> angeben schweben < 24> verwendet SQL Server < 24> intern schweben. Wenn Sie float oder irgendetwas in den Bereich float < 25> float < 53> (die Grenze) verwenden, verwendet es Float < 53> die ist sonst bekannt als doppelte Genauigkeit.

Meine Tabelle hat Feld vom Typ FLOAT die @Result FLOAT OUT von einer gespeicherten Prozedur mit dem Parameter gelesen und zurückgegeben.

Mein C# -Code wie folgt aussieht, beachten Sie verwendet es die Float Typ nicht Real:

//setting up the query 
command.Parameters.Add("@Result", SqlDbType.Float).Direction = ParameterDirection.Output; 

//reading the value 
double result = Convert.ToDouble(command.Parameters["@Result"].Value); 

Sollte dies funktionieren ... oder tut eine SqlServer FLOAT Arbeit anders als ein normaler double Typ in Sprachen wie C# ? Sollte 0,1 genau gespeichert werden und nicht zurückgegeben werden? Wenn ich Real verwenden würde, wäre ich nicht überrascht, aber ich dachte, Float sollte sehr genau sein. Oder zumindest hätte eine eingeschränkte Präzision falsche Zahlen nicht einzuführen ...

+2

Nein float ist ein ungefährer Datentyp und ist nicht vollständig genau. https://docs.microsoft.com/en-us/sql/t-sql/data-types/float-and-real-transact-sql –

+0

Nun, der Standard für Float ist 53 gibt es eine Genauigkeit von 15 Ziffern obwohl Du hast dort mehr Ziffern. Aber ich würde nur Dezimal (Länge, Präzision) verwenden – scsimon

+0

@SeanLange sicher, keine fp Darstellung kann absolut genau sein. Bei der Arbeit mit C# -Doppel-Typen sehe ich normalerweise keine Ungenauigkeiten wie diese. Ist es ein Unterschied in der Art und Weise, in der .Net und SqlServer Fließkommazahlen darstellen? –

Antwort

0

Führen Sie diese Abfrage aus, und beachten Sie, dass es eine endlose While-Schleife erstellt. Sie müssen die Ausführung manuell stoppen.

DECLARE @Counter float; 
SET @Counter = 0; 
WHILE (@Counter <> 1.0) BEGIN 
    SET @Counter += 0.1; 
    PRINT @Counter; 
END; 

Sie würden denken, dass es das gleiche sein würde, aber es ist nicht.

DECLARE @Counter decimal(4,2); 
SET @Counter = 0; 
WHILE (@Counter <> 1.0) BEGIN 
    SET @Counter += 0.1; 
    PRINT @Counter; 
END; 

Das Problem ist, dass 0,1 kann nicht genau in einem Float-Datentyp gespeichert werden. Ein dezimaler Datentyp muss verwendet werden.

Ein dezimaler Datentyp ist ein genauer numerischer Datentyp, wobei float ein ungefährer numerischer Datentyp ist. Hier ist eine Referenz, Link.

Der Grund, warum die Abfrage mit dem Float-Datentyp eine endlose while-Schleife erzeugt, liegt daran, dass ein ungefährer numerischer Datentyp NIEMALS gleich 1.0 ist.

+1

Es wäre gut zu erklären, warum die 'float'-Version eine Endlosschleife ist, im Gegensatz zur 'dezimalen' Version. Die Verwirrung darüber, warum sie anders sind, ist der Grund, warum die Frage (und viele andere) existiert. – krillgar

+0

krillgar, aktualisierte meine Antwort. – Jason

+0

Ein dezimaler Gleitkommatyp ist von Natur aus nicht mehr oder weniger genau als ein binärer Fließkommatyp. Sie unterscheiden sich lediglich in * welche * Zahlen genau mit diesem Typ gespeichert werden können. Einige Zahlen wie (1/3) können nicht genau im binären oder dezimalen Gleitkommaformat dargestellt werden. – njuffa