Czy liczba zmiennoprzecinkowa ma 32 cyfry binarne, a podwójna 64 cyfry binarne? Dokumentacja była zbyt trudna do zrozumienia.
Czy wszystkie bity są tłumaczone na cyfry znaczące? A może położenie przecinka dziesiętnego zajmuje część bitów?
java
floating-point
Eamon Moloney
źródło
źródło
Odpowiedzi:
float : 32 bity (4 bajty), gdzie mantysa ma 23 bity (około 7 cyfr dziesiętnych). 8 bitów jest używanych jako wykładnik, więc liczba zmiennoprzecinkowa może „przesuwać” przecinek dziesiętny w prawo lub w lewo za pomocą tych 8 bitów. W ten sposób unika się przechowywania wielu zer w mantysie, jak w 0,0000003 (3 × 10-7 ) lub 3000000 (3 × 10 7 ). Jako bit znaku używany jest 1 bit.
double : 64 bity (8 bajtów), gdzie mantysa ma 52 bity (około 16 cyfr dziesiętnych). 11 bitów jest używanych jako wykładnik, a 1 bit to bit znaku.
Ponieważ używamy liczby binarnej (tylko 0 i 1), jeden bit mantysy jest niejawnie równy 1 (zarówno zmiennoprzecinkowy, jak i podwójny używają tej sztuczki), gdy liczba jest różna od zera.
Ponadto, ponieważ wszystko jest binarne (mantysa i wykładniki), konwersje na liczby dziesiętne zwykle nie są dokładne. Liczby takie jak 0,5, 0,25, 0,75, 0,125 są przechowywane dokładnie, ale 0,1 nie. Jak powiedzieli inni, jeśli potrzebujesz precyzyjnie przechowywać centy, nie używaj float ani double, używaj int, long, BigInteger lub BigDecimal.
Źródła:
http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
http://en.wikipedia.org/wiki/Binary64
http://en.wikipedia.org/wiki/Binary32
źródło
double
i 7,2 dlafloat
, czyli 15 i 7. W każdym przypadku można przedstawić niektóre większe liczby i żadna z nich nie dotyczy ułamków, ale nie ma o tym „średniej”, a żadne z twoich źródeł nie mówi Inaczej.32-bitowy zmiennoprzecinkowy ma około 7 cyfr dokładności, a 64-bitowy podwójny ma około 16 cyfr precyzji
Długa odpowiedź:
Liczby zmiennoprzecinkowe mają trzy składniki:
Zasadniczo to działa
sign * 2^exponent * (1 + fraction)
. „Rozmiar” liczby, jej wykładnik, nie ma dla nas znaczenia, ponieważ skaluje tylko wartość części ułamkowej. Wiedząc, żelog₁₀(n)
daje to liczbę cyfrn
, † możemy określić dokładność liczby zmiennoprzecinkowej za pomocąlog₁₀(largest_possible_fraction)
. Ponieważ każdy bit w liczbie zmiennoprzecinkowej przechowuje 2 możliwości, binarna liczban
bitów może przechowywać liczbę do2ⁿ - 1
(łącznie2ⁿ
wartości, w których jedna z wartości wynosi zero). Staje się to nieco bardziej skomplikowane, ponieważ okazuje się, że liczby zmiennoprzecinkowe są przechowywane z jednym bitem ułamka mniejszym, niż mogą użyć, ponieważ zera są reprezentowane specjalnie, a wszystkie liczby niezerowe mają co najmniej jeden niezerowy bit binarny. ‡ ‡Łącząc to, cyfry dokładności dla liczby zmiennoprzecinkowej to
log₁₀(2ⁿ)
, gdzien
jest liczbą bitów ułamka liczby zmiennoprzecinkowej. 32-bitowa liczba zmiennoprzecinkowa ma 24 bity ułamka dla dokładności ≈7,22 cyfr dziesiętnych, a 64-bitowa podwójna ma 53 bity ułamka dla dokładności ≈15,95 cyfr dziesiętnych.Aby uzyskać więcej informacji na temat dokładności zmiennoprzecinkowej, możesz przeczytać o koncepcji epsilon maszynowej .
†
n ≥ 1
Przynajmniej - dla innych liczb Twój wzór będzie wyglądał bardziej jak⌊log₁₀(|n|)⌋ + 1
.‡ „Reguła ta jest różnie nazywana konwencją bitów wiodących, niejawną konwencją bitową lub konwencją ukrytego bitu”. ( Wikipedia )
źródło
Ze specyfikacji Java :
Ponieważ trudno jest zrobić cokolwiek z liczbami bez zrozumienia podstaw IEEE754, oto kolejny link .
Ważne jest, aby zrozumieć, że precyzja nie jest jednolita i że nie jest to dokładne przechowywanie liczb, jak ma to miejsce w przypadku liczb całkowitych.
Przykład :
double a = 0.3 - 0.1; System.out.println(a);
wydruki
0.19999999999999998
Jeśli potrzebujesz dowolnej precyzji (na przykład do celów finansowych), możesz potrzebować opcji Big Decimal .
źródło
Normalna odpowiedź matematyczna.
Rozumiejąc, że liczba zmiennoprzecinkowa jest zaimplementowana jako niektóre bity reprezentujące wykładnik, a pozostałe, w większości dla cyfr (w systemie binarnym), mamy następującą sytuację:
Przy wysokim wykładniku, powiedzmy 10²³, jeśli najmniej znaczący bit zostanie zmieniony, pojawi się duża różnica między dwoma sąsiednimi liczbami, które można odróżnić od siebie. Ponadto kropka dziesiętna o podstawie 2 sprawia, że wiele liczb o podstawie 10 można jedynie przybliżać; 1/5, 1/10 to nieskończone liczby.
Tak w ogóle : liczb zmiennoprzecinkowych nie powinny być stosowane, jeżeli dbasz o znaczących cyfr. W przypadku kwot pieniężnych z obliczeniami, e, a, najlepiej używać BigDecimal .
Dla fizyka zmiennoprzecinkowej dwuosobowe są wystarczające, unosi się prawie nigdy. Ponadto zmiennoprzecinkowa część procesorów, FPU, może nawet wewnętrznie używać nieco większej precyzji.
źródło
Liczby zmiennoprzecinkowe są kodowane przy użyciu postaci wykładniczej, czyli czegoś w rodzaju
m * b ^ e
, tj. W ogóle nie są liczbami całkowitymi. Pytanie, które zadasz, miałoby znaczenie w kontekście liczb stałych punktów . Dostępnych jest wiele bibliotek arytmetycznych punktów stałych .Odnośnie arytmetyki zmiennoprzecinkowej: Liczba cyfr dziesiętnych zależy od prezentacji i systemu liczbowego. Na przykład istnieją liczby okresowe (
0.33333
), które nie mają skończonej prezentacji w postaci dziesiętnej, ale mają ją w postaci binarnej i odwrotnie.Również warto wspomnieć, że liczb zmiennoprzecinkowych do pewnego stopnia mają różnicę większą niż jeden, czyli
value + 1
plonyvalue
, ponieważvalue + 1
nie mogą być kodowane przy użycium * b ^ e
, gdziem
,b
ie
są ustalone w długości. To samo dzieje się w przypadku wartości mniejszych niż 1, tj. Wszystkie możliwe punkty kodowe nie mają takiej samej odległości.Z tego powodu nie ma precyzji dokładnych
n
cyfr, jak w przypadku liczb stałych, ponieważ nie każda liczba zn
cyframi dziesiętnymi ma kodowanie IEEE.Istnieje prawie obowiązkowy dokument, który powinieneś przeczytać, wyjaśniający liczby zmiennoprzecinkowe: Co każdy informatyk powinien wiedzieć o arytmetyce zmiennoprzecinkowej .
źródło
Spójrz na
Float.intBitsToFloat
iDouble.longBitsToDouble
, które wyjaśnią, w jaki sposób bity odpowiadają liczbom zmiennoprzecinkowym. W szczególności kawałki normalnegofloat
wyglądu przypominająs * 2^exp * 1.ABCDEFGHIJKLMNOPQRSTUVW
gdzie A ... W to 23 bity - 0 i 1 - reprezentujące ułamek w postaci binarnej - s to +/- 1, reprezentowane odpowiednio przez 0 lub 1, a exp jest 8-bitową liczbą całkowitą ze znakiem.
źródło