Kod
float x = 3.141592653589793238;
double z = 3.141592653589793238;
printf("x=%f\n", x);
printf("z=%f\n", z);
printf("x=%20.18f\n", x);
printf("z=%20.18f\n", z);
da ci wyjście
x=3.141593
z=3.141593
x=3.141592741012573242
z=3.141592653589793116
gdzie w trzecim wierszu danych wyjściowych 741012573242
jest śmieci, a w czwartym wierszu 116
. Czy gra podwójna zawsze ma 16 cyfr znaczących, podczas gdy zmienna zawsze ma 7 cyfr znaczących? Dlaczego pary nie mają 14 cyfr znaczących?
źródło
__STDC_IEC_559__
. Implementacja, która nie definiuje tego makra, może nie być zgodna z IEEE-754.0.5
,0.046875
albo0.376739501953125
porównaniu ich reprezentacje po przecinku. (Są to wszystkie wymierne diadyczne z licznikiem pasującym do mantysy i logarytmem o podstawie-2 z mianownika pasującego do wykładnika.)Nie. Podwójne zawsze mają 53 znaczące bity, a zmiennoprzecinkowe zawsze 24 znaczące bity (z wyjątkiem denormali, nieskończoności i wartości NaN, ale są to tematy dla innego pytania). Są to formaty binarne i można jasno mówić tylko o precyzji ich reprezentacji w postaci cyfr binarnych (bitów).
Jest to analogiczne do pytania, ile cyfr może być przechowywanych w binarnej liczbie całkowitej: 32-bitowa liczba całkowita bez znaku może przechowywać liczby całkowite do 32 bitów, które nie są dokładnie odwzorowane na dowolną liczbę cyfr dziesiętnych: wszystkie liczby całkowite do Można zapisać 9 cyfr dziesiętnych, ale można również zapisać wiele liczb 10-cyfrowych.
Kodowanie podwójnej liczby wykorzystuje 64 bity (1 bit na znak, 11 bitów na wykładnik, 52 jawne znaczące bity i jeden niejawny bit), co stanowi dwukrotność liczby bitów użytych do przedstawienia liczby zmiennoprzecinkowej (32 bity).
źródło
float: 23 bity znacznika, 8 bitów wykładnika i 1 bit znaku.
double: 52 bity istotności, 11 bitów wykładnika i 1 bit znaku.
źródło
Zwykle opiera się na liczbach znaczących zarówno wykładnika, jak i istotności o podstawie 2, a nie o podstawie 10. Z tego, co mogę powiedzieć w standardzie C99, nie ma jednak określonej precyzji dla liczb zmiennoprzecinkowych i podwójnych (poza faktem, że 1 i
1 + 1E-5
/1 + 1E-7
są rozróżnialne [float
idouble
odpowiednio]). Jednak liczba cyfr znaczących pozostaje w gestii implementującego (a także z jakiej bazy korzysta wewnętrznie, więc innymi słowy, implementacja może zdecydować się na jej wykonanie w oparciu o 18 cyfr dokładności w bazie 3). [1]Jeśli chcesz znać te wartości, stałe
FLT_RADIX
iFLT_MANT_DIG
(iDBL_MANT_DIG
/LDBL_MANT_DIG
) są zdefiniowane w float.h.Powodem, dla którego nazywa się a,
double
jest to, że liczba bajtów użytych do jego przechowywania jest dwa razy większa niż liczba zmiennoprzecinkowa (ale obejmuje to zarówno wykładnik, jak i mantynę). Standard IEEE 754 (używany przez większość kompilatorów) przydziela relatywnie więcej bitów dla istotności niż wykładnik (23 do 9 wfloat
porównaniu z 52 do 12 w przypadkudouble
), dlatego precyzja jest ponad dwukrotnie większa.1: Sekcja 5.2.4.2.2 ( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf )
źródło
1E-9
fordouble
, not1E-7
.Liczba zmiennoprzecinkowa ma 23 bity precyzji, a podwójna 52.
źródło
Nie jest to dokładnie podwójna precyzja ze względu na sposób działania IEEE 754 i ponieważ binarny nie przekłada się dobrze na dziesiętne. Jeśli jesteś zainteresowany, spójrz na standard.
źródło
float oznacza liczbę zmiennoprzecinkową. W C typ danych zmiennoprzecinkowych jest używany w tych przypadkach, w których dokładność całkowitej liczby cyfr wynosi 7, np. Wartość 12.3546987 nie może zostać zapisana jako liczba zmiennoprzecinkowa, ponieważ ma w sumie 9 cyfr. Wyjście zostanie pokazane jako 12.354699, tj. Pierwsze 7 cyfr zostanie pokazanych zgodnie z wprowadzonymi danymi, a 8 cyfra zostanie zaokrąglona. Typ zmiennoprzecinkowy może przedstawiać wartości w zakresie od około 1,5 x 10 ^ (- 45) do 3,4 x 10 ^ (38). Pod względem alokacji pamięci, zmiennoprzecinkowy typ danych o pojedynczej precyzji, 32-bitowy zmiennoprzecinkowy.
W przeciwieństwie do liczby zmiennoprzecinkowej, double ma dokładność od 15 do 16 cyfr. Zakres double wynosi od 5,0 × 10 ^ (- 345) do 1,7 × 10 ^ (308). Pod względem alokacji bajtów, double to 64-bitowe dane zmiennoprzecinkowe rodzaj.
Problem pojawia się w jego użyciu. Float lub double nie wpływa na printf, ale w przypadku scanf należy użyć odpowiedniego typu danych w zależności od liczby całkowitej. cyfr w pływającym nr. to ma być odczytane z wejścia.
Dlatego double jest preferowany zamiast float, aby uzyskać większą dokładność danych.
Mam nadzieję że to pomoże.
źródło