Kiedy stosować zmiennoprzecinkowe vs dziesiętne


14

Buduję ten interfejs API, a baza danych będzie przechowywać wartości reprezentujące jedną z następujących czynności:

  • odsetek
  • średni
  • oceniać

Naprawdę nie mam pojęcia, jak przedstawić coś w przedziale od 0 do 100% liczbowo. Tak być powinno

  • 0,00 - 1,00
  • 0,00 - 100,00
  • każda inna alternatywa, której nie znam

Czy jest na to wyraźny wybór? Globalny sposób reprezentowania w bazach danych wartości od 0 do 100% procent? Idąc dalej, jaki jest odpowiedni dla niego typ, zmiennoprzecinkowy czy dziesiętny?

Dziękuję Ci.



5
Liczby mogą być przechowywane na wiele sposobów. Nie ma nic z natury złego w przechowywaniu wartości procentowej za pomocą 0-100 lub 0-1. Liczy się to, co musisz zrobić z liczbami, jakiej dokładności potrzebujesz i tak dalej. Musisz podać więcej kontekstu, zanim będzie można udzielić dobrej odpowiedzi. Czy potrzebujesz przechowywać liczby, które są dokładnie reprezentowalne za pomocą niewielkiej liczby cyfr dziesiętnych? Jeśli uśredniasz rzeczy, otrzymujesz ułamki takie jak trzecie lub siódme. Czy musisz je dokładnie przechowywać? A może w przybliżeniu? W przybliżeniu Co z nimi zrobisz?
Eric Postpischil

1
Jeśli wartości wynoszą od 0,00 do 100,00 w krokach co 0,01, to jest 10001 różnych wartości. Po prostu użyj intdo reprezentowania setnych lub w jednostkach Permyriad lub ‱.
chux - Przywróć Monikę

@ chux-ReinstateMonica - Tak, możliwe są „skalowane liczby całkowite”, ale niezgrabne.
Rick James

@RickJames Być może. Nie znalazłem trudnych skalowanych liczb całkowitych.
chux - Przywróć Monikę

Odpowiedzi:


4

Zajmę przeciwne stanowisko.

FLOATjest dla przybliżonych liczb, takich jak procenty, średnie itp. Powinieneś formatować, wyświetlając wartości, albo w kodzie aplikacji, albo przy użyciu FORMAT()funkcji MySQL.

Nigdy nie testuj float_value = 1.3; istnieje wiele powodów, dla których to się nie powiedzie.

DECIMALnależy stosować do wartości pieniężnych. DECIMALunika się drugiego zaokrąglania, gdy wartość należy zaokrąglić do dolarów / centów / euro / itp. Księgowi nie lubią ułamków centów.

Implementacja MySQL DECIMALpozwala na 65 cyfr znaczących; FLOATdaje około 7 i DOUBLEokoło 16. 7 jest zwykle więcej niż wystarczające dla czujników i obliczeń naukowych.

Jeśli chodzi o „procent” - czasami używam, TINYINT UNSIGNEDgdy chcę zużyć tylko 1 bajt pamięci i nie potrzebuję dużej precyzji; czasami użyłem FLOAT(4 bajty). Nie ma typu danych dostosowanego specjalnie do wartości procentowej. (Należy również pamiętać, że DECIMAL(2,0)nie może utrzymać wartości 100, więc technicznie będziesz potrzebować DECIMAL(3,0).)

Lub czasami użyłem wartości FLOAT, która miała wartość od 0 do 1. Ale wtedy musiałbym się upewnić, że pomnożymy przez 100, zanim wyświetli się „procent”.

Więcej

Wszystkie trzy „procentowe, średnie, częste” pachną jak pływaki, więc to byłby mój pierwszy wybór.

Jedno kryterium decydowania o typie danych ... Ile kopii wartości będzie istniało?

Jeśli masz tabelę zawierającą miliardy wierszy z kolumną procentową, rozważ, TINYINTże zajmie to 1 bajt (łącznie 1 GB), ale FLOATzajmie 4 bajty (łącznie 4 GB). OTOH, większość aplikacji nie ma tylu wierszy, więc może to nie mieć znaczenia.

Zgodnie z ogólną zasadą w „dokładnych” wartościach należy stosować formę INTlub DECIMAL. Rzeczy niedokładne (obliczenia naukowe, pierwiastki kwadratowe, dzielenie itp.) Powinny używać FLOAT(lub DOUBLE).

Ponadto formatowanie danych wyjściowych należy zwykle pozostawić interfejsowi aplikacji. Oznacza to, że chociaż „średnia” może być obliczona na „14.6666666 ...”, wyświetlacz powinien pokazywać coś w rodzaju „14.7”; jest to bardziej przyjazne dla ludzi. Tymczasem masz podstawową wartość, aby później zdecydować, że preferowanym formatowaniem wyjściowym jest „15” lub „14.667”.

Zakres „0,00 - 100,00” można wykonać przy FLOAT użyciu formatowania wyjściowego lub przy użyciu DECIMAL(5,2)(3 bajtów) z wcześniejszym ustaleniem, że zawsze będzie wymagana wskazana dokładność .


3

Ogólnie odradzam używanie float. Liczby zmiennoprzecinkowe reprezentują liczby w bazie-2, co powoduje, że niektóre (dokładne) liczby są zaokrąglane w górę w operacjach lub porównaniach, ponieważ po prostu nie można ich dokładnie zapisać w bazie-2. Może to prowadzić do zaskakujących zachowań.

Rozważ następujący przykład :

create table t (num float);
insert into t values(1.3);

select * from t;

| num |
| --: |
| 1.3 |

select * from t where num = 1.3;

| num |
| --: |

Porównanie liczby w podstawie 2 1.3nie powiodło się. To trudne.

Dla porównania, dziesiętne zapewniają dokładne odwzorowanie liczb skończonych w ich zakresie. Jeśli zmienisz floatna decimal(2, 1)w powyższym przykładzie, uzyskasz oczekiwane wyniki.


4
Ta odpowiedź jest fałszywa pod wieloma względami. „Dla porównania, dziesiętne mają mniejszy zakres, ale zapewniają dokładną reprezentację liczb skończonych w tym zakresie” jest fałszywe: Dziesiętny nie reprezentuje ⅓ dokładnie. „Niektóre (dokładne, skończone) liczby są zaokrąglane” jest niepoprawne; liczby nie są „zaokrąglane”. Konwersje i inne operacje mogą się zaokrąglać. Domyślny tryb zaokrąglania to najczęściej zaokrąglanie do najbliższego powiązania z parzystym, a nie zaokrąglanie w górę.
Eric Postpischil

4
Problemy z dokładnością nie wynikają z „liczb zmiennoprzecinkowych”, ale po prostu z reprezentacji liczbowych: wszystkie skończone reprezentacje liczbowe mają ograniczoną dokładność: zmiennoprzecinkowe, punkt stały, liczba całkowita, wymierna, dziesiętna, binarna, wszystko.
Eric Postpischil

2
Westchnienie. Co naprawiłeś? Mój komentarz mówi, że odpowiedź jest błędna, ponieważ mówi, że dziesiętny zapewnia dokładną reprezentację liczb w swoim zakresie, ale w rzeczywistości tak nie jest, ponieważ nie zapewnia dokładnej reprezentacji ⅓. Zmiana mówi „dokładny” zamiast „dokładny”, ale dlaczego nie jest binarny zmiennoprzecinkowy tak samo dobry - ani nie jest dokładny dla ⅓ i oba lub żadne nie są dokładne, w zależności od tego, jaki jest twój próg dokładności i ile precyzji oni mają. Pytanie wskazuje, że średnie będą reprezentowane, a uśrednienie trzech rzeczy daje liczby takie jak ⅓.
Eric Postpischil

4
Komentarz mówi, że najczęściej stosuje się zaokrąglenie do najbliższego powiązania z parzystym, ale odpowiedź wciąż mówi o zaokrągleniu w górę. Odpowiedź mówi, że porównania mogą zaokrąglać w górę, ale porównania są idealne: porównania zawsze zwracają matematycznie poprawny wynik, bez zaokrąglania. (Niektóre języki programowania mogą konwertować operandy przed porównaniem, ale są to osobne operacje.)
Eric Postpischil

1
1/3 nie może być dokładnie przedstawione w postaci binarnej ani dziesiętnej. Zniżka w wysokości 20% od 14,99 USD będzie wymagać zaokrąglenia ułamków ułamkowych, które nie istnieją.
Rick James

0

Różnica między liczbą zmiennoprzecinkową a dziesiętną polega na precyzji. Liczba dziesiętna może w 100% dokładnie reprezentować dowolną liczbę z dokładnością do formatu dziesiętnego, natomiast liczba zmiennoprzecinkowa nie może dokładnie reprezentować wszystkich liczb.

Użyj wartości dziesiętnych np. Dla wartości powiązanej z finansami, a liczby zmiennoprzecinkowej użyj np. Dla wartości powiązanej graficznie


0

Polecam używać, decimal(5,2)jeśli zamierzasz go przechowywać w taki sam sposób, w jaki go wyświetlasz, ponieważ decimalsłuży to zachowaniu dokładności. (Zobacz https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html )

Ponieważ wartości zmiennoprzecinkowe są przybliżone i nie są przechowywane jako dokładne wartości, próby traktowania ich jako dokładne w porównaniach mogą prowadzić do problemów. Podlegają również zależnościom platformy lub implementacji.

( https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html )

Wartość zmiennoprzecinkowa zapisana w instrukcji SQL może nie być taka sama jak wartość reprezentowana wewnętrznie.

W przypadku kolumn DECIMAL MySQL wykonuje operacje z dokładnością do 65 cyfr dziesiętnych, co powinno rozwiązać najczęstsze problemy z niedokładnością.

https://dev.mysql.com/doc/refman/8.0/en/problems-with-float.html


0

Dziesiętny: W przypadku aplikacji finansowych lepiej jest używać typów dziesiętnych, ponieważ zapewnia wysoki poziom dokładności i łatwe do uniknięcia błędy zaokrąglania

Podwójne: podwójne typy są prawdopodobnie najczęściej używanym typem danych dla rzeczywistych wartości, z wyjątkiem obsługi pieniędzy.

Float: Jest stosowany głównie w bibliotekach graficznych, ponieważ bardzo wysokie wymagania dotyczące mocy obliczeniowych, również w sytuacjach, które mogą znosić błędy zaokrąglania.

Odniesienie: http://net-informations.com/q/faq/float.html


0
mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G

*********************************************************************

@a := (a/3): 33.333333333
@b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100

Dziesiętny zrobił dokładnie to, co powinien zrobić w tych przypadkach, obciął resztę, tracąc w ten sposób część 1/3.

Tak więc dla sum lepsza jest liczba dziesiętna, ale dla podziałów liczba zmiennoprzecinkowa jest lepsza, do pewnego momentu, oczywiście. Mam na myśli, że użycie DECIMAL nie da ci „arytmetyki odpornej na błędy” w żaden sposób.

Mam nadzieję, że to pomoże.


0

W tsql: Float, 0.0 zapisuje jako 0 i nie wymaga definiowania po cyfrach dziesiętnych, np. Nie musisz pisać Float (4,2). Dziesiętny, 0.0 przechowuj jako 0.0 i ma opcję definiowania jak dziesiętny (4,2), sugerowałbym 0,00-1,00, robiąc to, możesz obliczyć wartość tego procentu bez pomnożenia przez 100, a jeśli raportujesz, to ustaw typ danych tej kolumny w procentach jak MS Excel i inne widoki platformy 0.5 -> 50%.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.