Różnica między liczbą, liczbą zmiennoprzecinkową i dziesiętną w programie SQL Server

322

Jakie są różnice między numeric, floati decimaltypy danych i które powinny być stosowane, w jakich sytuacjach?

Dla jakiejkolwiek transakcji finansowej (np. W dziedzinie wynagrodzeń), która jest preferowana i dlaczego?

priyanka.sarkar
źródło
1
Powyższy link dziesiętny i numeryczny wymaga aktualizacji do docs.microsoft.com/en-us/sql/t-sql/data-types/… . Powyższy link już nie istnieje.
Nigel Ainscoe
1
Zwykle w kontaktach z podmiotami finansowymi interesująca jest praca z typami całkowitymi , oprócz zmiennoprzecinkowych , i przechowywanie wartości w centach zamiast na przykład w dolarach .
Pedro

Odpowiedzi:

493

użyj pływak lub rzeczywiste typy danych tylko wtedy, gdy precyzja zapewnia przecinku (do 38 cyfr) jest niewystarczająca

  • Przybliżone numeryczne typy danych nie przechowują dokładnych wartości określonych dla wielu liczb; przechowują bardzo bliskie przybliżenie wartości. ( Technet )

  • Unikaj używania kolumn zmiennoprzecinkowych lub rzeczywistych w warunkach wyszukiwania klauzul WHERE, zwłaszcza operatorów = i <> ( Technet )

tak ogólnie, ponieważ dokładność zapewniona przez ułamek dziesiętny wynosi [10E38 ~ 38 cyfr], jeśli twój numer może się do niego zmieścić, a mniejsza przestrzeń do przechowywania (i być może szybkość) Float nie jest ważna, a radzenie sobie z nienormalnymi zachowaniami i problemami z przybliżonymi typami liczbowymi nie są dopuszczalne, ogólnie używaj dziesiętnego .

więcej przydatnych informacji

  • numeryczny = dziesiętny (od 5 do 17 bajtów) ( Dokładny numeryczny typ danych)
    • zamapuje na dziesiętny w .NET
    • oba mają (18, 0) jako domyślne parametry (precyzja, skala) w serwerze SQL
    • skala = maksymalna liczba cyfr dziesiętnych, które można zapisać po prawej stronie przecinka.
    • uprzejmie pamiętaj, że pieniądze (8 bajtów) i smallmoney (4 bajty) są również dokładne i odwzorowane na dziesiętne w .NET i mają 4 kropki dziesiętne ( MSDN )
    • dziesiętny i numeryczny (Transact-SQL) - MSDN
  • rzeczywisty (4 bajty) ( przybliżony numeryczny typ danych)
  • zmiennoprzecinkowy (8 bajtów) ( przybliżony typ danych liczbowych)
    • zamapuje na Double w .NET
  • Wszystkie dokładne typy liczbowe zawsze dają ten sam wynik, bez względu na to, jaki rodzaj architektury procesora jest używany, czy też wielkość liczb
  • Parametr dostarczony do typu danych zmiennoprzecinkowych określa liczbę bitów używanych do przechowywania mantysy liczby zmiennoprzecinkowej .
  • Przybliżony numeryczny typ danych zwykle zużywa mniej miejsca i ma lepszą prędkość (do 20x), a także należy rozważyć, kiedy zostaną przekonwertowane w .NET

Dokładne typy danych numerycznych Przybliżone liczbowe typy danych

główne źródło : Zestaw do samodzielnego szkolenia MCTS (egzamin 70-433): Rozwój bazy danych Microsoft® SQL Server® 2008 - Rozdział 3 - Tabele, typy danych i deklaratywna integralność danych Lekcja 1 - Wybór typów danych (wytyczne) - Strona 93

Iman
źródło
17
use the float or real data types only if the precision provided by decimal is insufficient- Myślałem, że prawdziwe jest MNIEJ dokładniejsze niż dziesiętne, więc dlaczego piszesz, aby używać prawdziwego, jeśli dziesiętny jest niewystarczający?
BornToCode,
7
wartość rzeczywista jest mniej dokładna, więc nie jest zalecane, chyba że konieczne jest przechowywanie dużych liczb większych niż dziesiętne (> 10e38) lub względy dotyczące przestrzeni. wydaje się, że precyzja tutaj w cytacie oznacza możliwe wartości i wielkość, a nie dokładność
Iman
11
@BornToCode „Precyzja” odnosi się tutaj do tego, jak szerokie są wartości, które chcesz przechowywać. jeśli chcesz przechowywać wartości między 1e10 a 1e-10, decimalbędzie dobrze. Dokładność wynosi 20. Jeśli chcesz przechowywać wartości między, powiedzmy, 1e20 a 1e-20, cóż, decimal nie możesz tego zrobić. To 40 cyfr precyzji. Nie możesz nigdy przechowywać 1e20 i 1e-20 w tym samym decimalpolu. Zamiast tego możesz użyć float, który wewnętrznie przechowuje wszystko jako log podstawy 2. To pozwala na pełny zakres precyzji w jednym polu z wadą, że tylko pierwsze ~ 8 cyfr będą dokładne.
Bacon Bits
Trzeci komentarz BornToCode i Iman. Właśnie eksperymentowałem (używając SQL Server 2012) i wydaje się, że maszyna epsilon dla float (53), najbardziej zmiennoprzecinkowy typ precyzji, to 2.22044604925031E-16. Otrzymasz z tego około 15 znaczących liczb. Z drugiej strony mogę uzyskać 38 cyfr po przecinku.
Stewart
„Użyj float...” - powiedział kto? Czy to cytat czy twoja opinia?
user443854
24

Wytyczne MSDN: Używanie danych dziesiętnych, zmiennoprzecinkowych i rzeczywistych

Domyślna maksymalna dokładność liczbowych i dziesiętnych typów danych wynosi 38. W Transact-SQL liczba jest funkcjonalnie równoważna dziesiętnemu typowi danych. Użyj dziesiętnego typu danych do przechowywania liczb dziesiętnych, gdy wartości danych muszą być przechowywane dokładnie tak, jak określono.

Zachowanie zmiennoprzecinkowe i rzeczywiste jest zgodne ze specyfikacją IEEE 754 dotyczącą przybliżonych typów danych liczbowych. Ze względu na przybliżony charakter danych zmiennoprzecinkowych i rzeczywistych typów danych nie należy używać tych typów danych, gdy wymagane jest dokładne zachowanie numeryczne, na przykład w aplikacjach finansowych, w operacjach obejmujących zaokrąglanie lub w kontrolach równości. Zamiast tego użyj typów danych liczb całkowitych, dziesiętnych, pieniężnych lub smallmoney. Unikaj używania kolumn zmiennoprzecinkowych lub rzeczywistych w warunkach wyszukiwania klauzul WHERE, szczególnie operatorów = i <>. Najlepiej jest ograniczyć liczby zmiennoprzecinkowe i rzeczywiste do> lub <porównań.

kmote
źródło
(Stała) liczba miejsc po przecinku jest określona w Scalekolumnie.
Cees Timmerman,
1
Jeśli chcesz „dokładnie tak, jak określono”, to z punktu widzenia standardów jest pewna zaleta, numericponieważ nigdy nie będzie przechowywać z większą precyzją, niż prosiłeś: patrz stackoverflow.com/a/759606/626804
Ed Avis
13

Nie pełna odpowiedź, ale przydatny link:

„Często wykonuję obliczenia w oparciu o wartości dziesiętne. W niektórych przypadkach rzutowanie wartości dziesiętnych na zmienne jak najszybciej, przed wszelkimi obliczeniami, daje lepszą dokładność”.

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/12/20/for-better-precision-cast-decimals-before-calculations.aspx

AK
źródło
2
To nie ma sensu. Wszystkie inne odpowiedzi, wraz ze źródłami, mówią, że typy danych liczbowych lub dziesiętnych są dokładne, a typy zmiennoprzecinkowe lub rzeczywiste są bardzo zbliżone. Ze względu na niższą dokładność rozumiem, że rzutowanie na zmiennoprzecinkowe może pozwolić na szybsze obliczenia, ale nie na większą precyzję.
cbaldan
3
Wszystkie typy danych numerycznych mogą podlegać przepełnieniu i niedopełnieniu. Przepełnienie jest wyraźnym błędem, jednak niedomiar jest cichy. Charakterystyka niedomiaru dla decimali floatróżne . Liczby dziesiętne chronią przed niedopełnieniem w jak największym stopniu poprzez zwiększenie precyzji lub skali. Jednak po osiągnięciu limitu znaczących cyfr po przecinku niedomiar jest cichy (a precyzja jest tracona). Pływak ma szerszy możliwy zakres skali, a jej ograniczenia w rzeczywistości są przyczyną niedomiaru. Dlatego float może mieć lepszą skalę. Niemniej jednak jest to wciąż niedokładny typ.
ErikE
13

Różnią się priorytetem typów danych

Dziesiętny i numeryczny są takie same funkcjonalnie, ale nadal istnieje pierwszeństwo typu danych , które może być kluczowe w niektórych przypadkach.

SELECT SQL_VARIANT_PROPERTY(CAST(1 AS NUMERIC) + CAST(1 AS DECIMAL),'basetype')

Wynikowy typ danych jest liczbowy, ponieważ ma pierwszeństwo dla typu danych .

Wyczerpująca lista typów danych według pierwszeństwa:

Link referencyjny

Stephan
źródło
7

Dziesiętny ma stałą precyzję, a zmiennoprzecinkowy zmienną.

EDYCJA (nie przeczytałem całego pytania): Liczba zmiennoprzecinkowa (53) (znana również jako rzeczywista) jest liczbą zmiennoprzecinkową podwójnej precyzji (32-bit) w programie SQL Server. Regular Float to liczba zmiennoprzecinkowa pojedynczej precyzji. Double to dobre połączenie precyzji i prostoty do wielu obliczeń. Możesz utworzyć bardzo dokładną liczbę dziesiętną - do 136-bitów - ale musisz również uważać, aby poprawnie zdefiniować swoją precyzję i skalować, aby zawierała wszystkie obliczenia pośrednie do niezbędnej liczby cyfr.

Brian Reiter
źródło
Nie określiłeś, który jest lepszy, gdy sprawa dotyczy transakcji finansowych i dlaczego?
priyanka.sarkar
W SQL Server 2008 i nowszych wersjach liczb zmiennoprzecinkowych float (53) aka jest liczbą zmiennoprzecinkową podwójnej precyzji (64-bit), a float (24) aka real to liczba zmiennoprzecinkowa pojedynczej precyzji (32-bit) docs.microsoft.com/en-us/sql/t-sql/data-types/float-and-real-transact-sql
M Kloster
4

Liczba zmiennoprzecinkowa jest typem danych o przybliżonej liczbie, co oznacza, że ​​nie wszystkie wartości w zakresie typów danych mogą być dokładnie reprezentowane.

Dziesiętny / Numeryczny jest typem danych o stałej precyzji, co oznacza, że ​​wszystkie wartości w zakresie typów danych mogą być dokładnie przedstawione z dokładnością i skalą. Aby zaoszczędzić pieniądze, możesz użyć dziesiętnego.

Konwersja z dziesiętnej lub numerycznej na zmiennoprzecinkową może spowodować utratę precyzji. W przypadku dziesiętnych lub liczbowych typów danych SQL Server traktuje każdą konkretną kombinację precyzji i skali jako inny typ danych. DECIMAL (2,2) i DECIMAL (2,4) to różne typy danych. Oznacza to, że 11.22 i 11.2222 są różnymi typami, chociaż nie jest tak w przypadku float. Dla FLOAT (6) 11.22 i 11.2222 są tymi samymi typami danych.

Możesz także użyć typu danych pieniędzy do oszczędzania pieniędzy. Jest to rodzimy typ danych z 4-cyfrową precyzją dla pieniędzy. Większość ekspertów woli ten typ danych dla oszczędności pieniędzy.

Odniesienie 1 2 3

Somnath Muluk
źródło
3

Przypadek dziesiętny

Jaka jest podstawowa potrzeba?

Wynika to z faktu, że ostatecznie komputery wewnętrznie reprezentują liczby w formacie binarnym. Prowadzi to nieuchronnie do błędów zaokrąglania.

Rozważ to:

0.1 (decimal, or "base 10") = .00011001100110011... (binary, or "base 2")

Powyższa elipsa [...] oznacza „nieskończony”. Jeśli przyjrzysz się temu uważnie, pojawi się nieskończony powtarzający się wzór (= „0011”)

W pewnym momencie komputer musi zaokrąglić tę wartość. Prowadzi to do błędów akumulacji wynikających z wielokrotnego używania liczb, które są niedokładnie przechowywane.

Powiedz, że chcesz przechowywać kwoty finansowe (które są liczbami, które mogą mieć część ułamkową). Po pierwsze, nie można oczywiście używać liczb całkowitych (liczby całkowite nie mają części ułamkowej). Z czysto matematycznego punktu widzenia naturalną tendencją byłoby użycie float. Ale w komputerze liczby zmiennoprzecinkowe mają tę część liczby, która znajduje się po przecinku - „mantysa” - ograniczona. Prowadzi to do błędów zaokrąglania.

Aby temu zaradzić, komputery oferują określone typy danych, które ograniczają błąd zaokrąglania binarnego w komputerach dla liczb dziesiętnych. Są to typy danych, które należy bezwzględnie wykorzystać do przedstawienia kwot finansowych. Te typy danych zwykle mają nazwę Decimal. Tak jest na przykład w języku C #. Lub DECIMALw większości baz danych.

Varus Septimus
źródło
1

Chociaż pytanie nie zawierało typu danych PIENIĄDZE, niektórzy ludzie przechodzący przez ten wątek mogą ulec pokusie użycia typu danych PIENIĄDZE do obliczeń finansowych.

Uważaj na typ danych PIENIĄDZE, ma on ograniczoną precyzję.

Istnieje wiele dobrych informacji na ten temat w odpowiedziach na to pytanie Stackoverflow:

Czy należy wybrać typy danych PIENIĄDZE lub DECIMAL (x, y) w SQL Server?

Simon Tewsi
źródło