2008-09-23 9 views
39

Howdy, ich habe eine DataRow aus einer DataTable aus einem DataSet abgerufen. Ich greife auf eine Spalte zu, die in SQL als Float-Datentyp definiert ist. Ich versuche, diesen Wert auf eine lokale Variable (C# float-Datentyp) zuweisen, sondern eine InvalidCastExecptionWarum unterscheidet sich ein SQL-Float von einem C# -Floss

DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65); 
_AccelLimit = (float)exercise["DefaultAccelLimit"]; 

Jetzt bin immer, das Spiel mit dieser ich habe es funktioniert, aber es hat keinen Sinn, und es didn‘ Ich fühle mich richtig.

_AccelLimit = (float)(double)exercise["DefaultAccelLimit"]; 

Kann mir jemand erklären, was mir hier fehlt?

Antwort

67

Ein SQL-Float ist ein Double nach the documentation for SQLDbType.

+7

Sie sind ähnlich, aber sicherlich nicht gleichwertig. Double unterstützt die Werte von + Infinity, -Infinity und NaN - gemäß der IEEE-Spezifikation, aber SQL float definitiv nicht. und wird Überlauffehler werfen. – Alain

+0

Ich stimme den Kommentaren von Alain May zu, aber ich verstehe noch nicht, warum. Ich habe Fälle gesehen, in denen .net double Zahlen repräsentiert, die SQL float brechen. Beispiele sind Unendlichkeitswerte und bestimmte negative Exponenten, die sich Null nähern. Ich vermute, dass MS für Speichereffizienz optimiert ist. – RaoulRubin

+1

@RaoulRubin: Siehe [MSDN-Dokumentation für TSQL-Floats] (https://msdn.microsoft.com/en-us/library/ms173773.aspx). Sie erwähnen niemals die IEEE-Konformität und geben an, dass sie einem unbenannten ISO-Standard folgt. Eine schnelle Suche ergibt [ISO/IEC 10967] (https://en.wikipedia.org/wiki/ISO/IEC_10967), die besagt, dass es mit IEEE 754 kompatibel ist, aber keine vollständige Implementierung garantiert. –

22

Ein Float in SQL ist ein Double in der CLR (C#/VB). Es gibt a table of SQL data types with the CLR equivalents auf MSDN.

+4

Sie sind ähnlich, aber sicherlich nicht gleichwertig. Double unterstützt die Werte von + Infinity, -Infinity und NaN - gemäß der IEEE-Spezifikation, aber SQL float definitiv nicht. und wird Überlauffehler werfen. Hoffentlich wird MSDN dies zu ihren Info-Seiten hinzufügen. – Alain

+1

Ok. Also, was ist deine Antwort? – Chookoos

2

Das Float in Microsoft SQL Server entspricht einem Double in C#. Der Grund dafür ist, dass eine Fließkommazahl nur eine Dezimalzahl approximieren kann, die Genauigkeit einer Fließkommazahl bestimmt, wie genau diese Zahl ungefähr eine Dezimalzahl ist. Der Double-Typ repräsentiert eine 64-Bit-Fließkommazahl mit doppelter Genauigkeit mit Werten von negativ 1.79769313486232e308 bis positiv 1.79769313486232e308 sowie positiv oder negativ Null, PositiveInfinity, NegativeInfinity und Not-a-Number (NaN).

2

Und normalerweise würden Sie nie float in SQL Server (oder real) verwenden möchten, wenn Sie mathematische Berechnungen für die Daten ausführen möchten, da es sich um einen ungenauen Datentyp handelt und Rechenfehler auftreten. Verwenden Sie stattdessen einen Dezimal-Datentyp, wenn Sie Genauigkeit benötigen.

+4

Es ist OK für die meisten mathematischen und technischen Berechnungen. Nun sind die * Finanz- und Buchhaltungsberechnungen natürlich anders. – Constantin

0

Ich denke, die Hauptfrage wurde hier beantwortet, aber ich fühle mich gezwungen, etwas für den Abschnitt der Frage hinzuzufügen, die besagt, dass dies funktioniert.

_AccelLimit = (float) (double) Übung ["DefaultAccelLimit"];

Der Grund dieses „Werk“ und der Grund, warum es „nicht richtig anfühlt“ ist, dass man durch die zweite Besetzung (der auf der linken Seite), um die Doppel mit einem Schwimmer ist Herabstufung, so dass Sie verlieren Präzision und Effektiv dem Compiler mitteilen, dass es in Ordnung ist, den zurückgegebenen Wert zu kürzen.

In Worten diese Zeile gibt ... Erhalten Sie ein Objekt (das geschieht mit einem Doppel in diesem Fall halten) in das Objekt Cast zu einem doppelten (Verlust der alle Objekt Verpackung) die Doppelbesetzung in mit einem Schwimmer (verliert die ganze feine Präzision eines Doppel)

zB Wenn der Wert sagen ,0124022806089461 und Sie die oben tun, dann wird der Wert von AccelLimit 0,01240228

sein wie das ist, das Ausmaß dessen, was ein Schwimmer in C# aus dem doppelten Wert erhalten. Es ist eine gefährliche Sache zu tun, und ich bin mir ziemlich sicher, dass es eine Kürzung auch eher als eine Rundung ist, aber jemand möchte das bestätigen, da ich nicht sicher bin.

0

Der Grund ist es „fühlt sich nicht richtig“ ist, weil C# die gleiche Syntax für Unboxing und für verwendet Gießen, das sind zwei sehr verschiedene Dinge.exercise["DefaultAccelLimit"] enthält einen doppelten Wert, eingerahmt als Objekt. (double) ist erforderlich, um unbox das Objekt wieder in ein Doppelzimmer. Die (float) vor, dass dann wirft die Doppel auf einen Float-Wert. C# erlaubt nicht das Boxen und Casting in der gleichen Operation, also musst du die Box auspacken und dann casten.

Das gleiche gilt auch, wenn die Besetzung nicht zerstörenden ist. Wenn ein Float als ein Objekt in ein Double-Objekt umgewandelt wurde, würden Sie es so machen: (double)(float)object_var.