Co stanowi podwójne w serwerze SQL?

335

Mam kilka właściwości, w C#których są doublei chcę je przechowywać w tabeli w SQL Server, ale zauważyłem, że nie ma doubletypu, więc co najlepiej użyć, decimalczy float?

Spowoduje to zapisanie wartości szerokości i długości geograficznej, więc potrzebuję najdokładniejszej precyzji.

Dzięki za dotychczasowe odpowiedzi.

Xaisoft
źródło
Oto mapowania typów danych CLR na SQL Server: http://msdn.microsoft.com/en-us/library/system.data.sqldbtype.aspx
Achilles
Jest świetny wątek na MSDN opisujący podstawową różnicę między FLOAT a DECIMAL. Krótko mówiąc, zmiennoprzecinkowe jest przybliżone i nie może reprezentować niektórych wartości. Spójrz na zaakceptowaną odpowiedź.
Matthew Jones

Odpowiedzi:

387
float

Lub jeśli chcesz iść do starej szkoły:

real

Możesz także użyć float (53), ale oznacza to to samo, co float.

(„real” jest równoważne z float (24), a nie float / float (53).)

Typ dziesiętny (x, y) SQL Server służy do tego, kiedy chcesz dokładnych liczb dziesiętnych zamiast liczb zmiennoprzecinkowych (które mogą być przybliżone). Jest to w przeciwieństwie do typu danych „dziesiętnych” w C #, który jest bardziej podobny do 128-bitowej liczby zmiennoprzecinkowej.

Typ zmiennoprzecinkowy MSSQL jest równoważny 64-bitowemu podwójnemu typowi w .NET. (Moja pierwotna odpowiedź z 2011 roku powiedziała, że ​​może być niewielka różnica w mantysie, ale przetestowałem to w 2020 roku i wydają się być w 100% kompatybilne pod względem binarnej reprezentacji zarówno bardzo małych, jak i bardzo dużych liczb - patrz https: / /dotnetfiddle.net/wLX5Ox dla mojego testu).

Aby bardziej skomplikować sprawę, „liczba zmiennoprzecinkowa” w języku C # jest tylko 32-bitowa, więc byłaby bardziej równoważna w SQL z typem rzeczywistym / float (24) w MSSQL niż zmienna / zmiennoprzecinkowa (53).

W twoim konkretnym przypadku użycia ... Wszystko czego potrzebujesz to 5 miejsc po przecinku, aby przedstawić szerokość i długość geograficzną z dokładnością około jednego metra, a potrzebujesz tylko trzech cyfr przed przecinkiem dla stopni. Liczba zmiennoprzecinkowa (24) lub dziesiętna (8,5) najlepiej pasuje do twoich potrzeb w MSSQL, a użycie zmiennoprzecinkowe w C # jest wystarczająco dobre, nie potrzebujesz podwójnej. W rzeczywistości Twoi użytkownicy prawdopodobnie będą ci wdzięczni za zaokrąglenie do 5 miejsc po przecinku, zamiast zebrać kilka nieistotnych cyfr podczas jazdy.

richardtallent
źródło
1
Mówisz, float, Dawid mówi dziesiętny, teraz jestem jeszcze bardziej mylić :)
Xaisoft
Używam podwójnych w c # i te wartości będą wartościami szerokości i długości geograficznej w odpowiednich kolumnach.
Xaisoft
1
Muszę się zgodzić i przyznać, że nie byłem w bazie. Wprowadzono mnie do systemu dziesiętnego w świecie IBM DB2, gdzie dziesiętny jest prawdziwym typem danych, obsługiwanym przez wszystkie wersje kodu i bazy danych na platformach IBM. Nie chodzi o to, że nie jest to prawdziwy typ danych w świecie MS, ale nie jest obsługiwany tak dobrze, jak w obozie IBM. Przepraszamy za zamieszanie.
DaveN59,
2
„Liczba zmiennoprzecinkowa MSSQL nie ma dokładnie takiej samej precyzji, jak 64-bitowy podwójny typ w .NET (niewielka różnica w Mantissa IIRC), ale jest wystarczająco blisko większości zastosowań.” Czy masz na to referencje? O ile widzę, oba używają 53 bitów znaczenia, używają 64 bitów do przechowywania, i mają taki sam układ bitów i znaczenie jak IEEE 754.
codekaizen
2
Jestem również bardzo ciekawy pytania postawionego przez @codekaizen (niewielka różnica w mantysie). Czy masz referencję lub test, który to ilustruje?
Mads Ravn
62

Również tutaj jest dobra odpowiedź na mapowanie typów SQL-CLR z przydatnym wykresem.

Z tego postu (autorstwa Davida ): wprowadź opis zdjęcia tutaj

Mazdak Shojaie
źródło
Poniżej link również użytkowania; zawiera dodatkowe informacje do powyższego, ponieważ pokazuje procedury i wyliczenia SqlDataReader (oprócz porównań typu .NET i SQL) docs.microsoft.com/en-us/dotnet/framework/data/adonet/…
d219
15

float jest najbliższym odpowiednikiem.

Wyliczenie SqlDbType

Dla Lat / Long jak wspomniano OP.

Metr to 1/40 000 000 szerokości geograficznej, 1 sekunda to około 30 metrów. Float / double daje 15 znaczących liczb. W przypadku szybkiej i podejrzanej arytmetyki umysłowej ... błędy zaokrąglania / aproksymacji byłyby mniej więcej długości tego zatrzymania napełniania -> „”.

gbn
źródło
1
Sprzedaj swój ekran Apple i zarabiaj miliardy! (Szybka arytmetyka mówi mi, że masz najbardziej ekstremalną rozdzielczość, o jakiej kiedykolwiek słyszałem, nawet na szerokościach geograficznych blisko Bieguna Północnego / Południowego; około miliarda razy wyższą niż moja).
Jonas Byström
10

Powinieneś odwzorować go na FLOAT (53) - właśnie to robi LINQ na SQL .

RichardOD
źródło
8

float w SQL Server faktycznie ma [edytuj: prawie] precyzję „podwójnej” (w sensie C #).

floatjest synonimem float(53). 53 to kawałki mantysy.

.NET doubleużywa 54 bitów dla mantysy.

Euro Micelli
źródło
2
W rzeczywistości IIRC, podwójne w .NET używa 52-bitowej mantysy i 11-bitowego wykładnika.
richardtallent
Będę cholerny; masz rację! Zastanawiam się, co robi SQL z dodatkowym bitem; nie jest używane dla wykładnika wykładniczego. Gdyby tak było, wykładnik wzrósłby do + -616 zamiast + -308. Może śledzić NULL?
Euro Micelli
Teraz jestem zdezorientowany. Każdy dowód wskazuje na to, że używają tego samego formatu (jak wszystko inne w systemie Windows). A dlaczego by nie mieli? Nie mogę znaleźć określonej instrukcji na temat reprezentacji bitowej w SQL Server (oprócz strony pomocy dla float). Wyślę korektę, jeśli się dowiem.
Euro Micelli
5

W przypadku serwera SQL Sever:

Typ dziesiętny to 128-bitowa liczba ze znakiem Liczba zmiennoprzecinkowa to 64-bitowa liczba ze znakiem.

Prawdziwa odpowiedź to Float , myliłem się co do dziesiętnych.

Powodem jest to, że jeśli użyjesz dziesiętnego, nigdy nie wypełnisz 64-bitowego typu dziesiętnego.

Chociaż liczba dziesiętna nie spowoduje błędu, jeśli spróbujesz użyć typu int.

Oto ładna tabela typów.

David Basarab
źródło
Teraz jest to jeszcze bardziej mylące z dwiema różnymi odpowiedziami: p
Xaisoft,
1
Nie mylcie się. Ta odpowiedź jest zła. Dziesiętny jest typem podstawowym-10; Float (w SQL Server i CLR) jest typu base-2.
Michael Petrotta
3

Wygląda na to, że możesz wybrać. Jeśli wybierzesz liczbę zmiennoprzecinkową, możesz stracić 11 cyfr precyzji. Jeśli jest to do zaakceptowania, wybierz to - najwyraźniej projektanci Linq uważali to za dobry kompromis.

Jeśli jednak aplikacja potrzebuje tych dodatkowych cyfr, użyj wartości dziesiętnych. Liczba dziesiętna (poprawnie zaimplementowana) jest znacznie dokładniejsza niż liczba zmiennoprzecinkowa - brak niechlujnego tłumaczenia z bazy 10 na bazę 2 i odwrotnie.

DaveN59
źródło
Służy do przechowywania wartości szerokości i długości geograficznej. Czy to robi różnicę?
Xaisoft
Jest to po prostu złe ... zarówno float / float (53) w MSSQL, jak i double w C # mają około 15 cyfr precyzji. Nie są dokładnie takie same, ale wystarczająco blisko. Z drugiej strony przecinek dziesiętny jest całkowitym nadmiarem do przechowywania podwójnego i musi wrócić do bazy 2 dla wszystkich obliczeń w SQL Server i wrócić do C # jako podwójny.
richardtallent
Poprawiono mnie. To, co mówisz, ma dla mnie idealny sens. Dziesiętny ma sens tylko wtedy, gdy wszędzie jest przechowywany jako wartość dziesiętna. Tracisz wartość za każdym razem, gdy wykonujesz konwersję z bazy 10 na bazę 2 (iz powrotem).
DaveN59,
-2

A Floatreprezentuje doublena serwerze SQL. Możesz znaleźć dowód z kodowania w C # w studio wizualnym. Tutaj zadeklarowałem Overtimejako Floatw SQL Server i w C #. W ten sposób jestem w stanie nawrócić

int diff=4;
attendance.OverTime = Convert.ToDouble(diff);

Tutaj OverTimejest zadeklarowanefloat type

Md Shoriful Islam
źródło