Czy ktoś może wyjaśnić reprezentację pływaka w pamięci?

20

To nie jest duplikat pytania, gdy czytam poprzednie pytanie.

Czy ktoś może mi pomóc w zrozumieniu how float values are stored in the memory.

Mam wątpliwości, czy tutaj wartości zmiennoprzecinkowe zawierają „ .'( for example 3.45) jak '.'będą reprezentowane w pamięci?

Czy ktoś może mi wyjaśnić za pomocą diagramu?

użytkownik2720323
źródło
21
A co z najmniej oczekiwanym źródłem, Wikipedią? en.wikipedia.org/wiki/Floating_point#Internal_representation
9000
4
I możesz dodać główny artykuł: zmiennoprzecinkowy IEEE
mouviciel
4
Jeśli jesteś podobny do mnie i lubisz się uczyć, bawiąc się różnymi
KChaloux
Istnieje wiele różnych formatów zmiennoprzecinkowych, wszystkie różne. Zmienna zmiennoprzecinkowa IEEE jest obecnie najczęstsza, ale nie tylko. Kiedy byłem studentem, musiałem nauczyć się formatu zmiennoprzecinkowego CDC 6600 i miał on pewne zalety w porównaniu z IEEE, z których największy to 48 bitów mantysy dla pojedynczej precyzji. IEEE jest ograniczone do około 24 bitów mantysy dla pojedynczej precyzji, dlatego każda wprowadzająca klasa metod numerycznych obecnie mówi uczniom: „Zawsze używaj podwójnego, a nie zmiennoprzecinkowego”.
John R. Strohm
Zobacz floating-point-gui.de i zapamiętaj ten adres URL
Basile Starynkevitch

Odpowiedzi:

44

Kropka dziesiętna nie jest nigdzie wyraźnie zapisywana; to problem z wyświetlaniem.

Poniższe wyjaśnienie stanowi uproszczenie; Pomijam wiele ważnych szczegółów, a moje przykłady nie mają reprezentować żadnej rzeczywistej platformy. Powinno to dać ci wyobrażenie o tym, jak wartości zmiennoprzecinkowe są reprezentowane w pamięci i związanych z nimi problemach, ale będziesz chciał znaleźć bardziej wiarygodne źródła, takie jak Co każdy informatyk powinien wiedzieć o arytmetyce zmiennoprzecinkowej .

Zacznij od przedstawienia wartości zmiennoprzecinkowej w wariancie notacji naukowej, używając podstawy 2 zamiast podstawy 10. Na przykład wartość 3.14159 można przedstawić jako

    0,7853975 * 2 2

0.7853975 to znaczenie , czyli mantysa; jest to część liczby zawierająca cyfry znaczące. Wartość tę mnoży się przez podstawę 2 podniesioną do potęgi 2, aby uzyskać 3,14159.

Liczby zmiennoprzecinkowe są kodowane przez przechowywanie znaczenia i wykładnika (wraz z bitem znaku).

Typowy układ 32-bitowy wygląda mniej więcej tak:

 3 32222222 22211111111110000000000
 1 09876543 21098765432109876543210
+-+--------+-----------------------+
| |        |                       |
+-+--------+-----------------------+
 ^    ^                ^
 |    |                |
 |    |                +-- significand 
 |    |
 |    +------------------- exponent 
 |
 +------------------------ sign bit

Podobnie jak podpisane typy liczb całkowitych, bit najwyższego rzędu wskazuje znak; 0 oznacza wartość dodatnią, 1 oznacza ujemną.

Kolejnych 8 bitów jest używanych dla wykładnika. Wykładniki mogą być dodatnie lub ujemne, ale zamiast rezerwować kolejny bit znaku, są one kodowane w taki sposób, że 10000000 reprezentuje 0, więc 00000000 reprezentuje -128, a 11111111 reprezentuje 127.

Pozostałe bity są używane dla znaczenia. Każdy bit reprezentuje ujemną moc 2 licząc od lewej, więc:

    01101 * 2 = 0 -1 + 1 * 2 -2 + 1 * 2 -3 + 0 * 2 -4 + 1 * 2 -5 
          = 0,25 + 0,125 + 0,03125 
          = 0,40625

Niektóre platformy zakładają „ukryty” bit wiodący w znaczeniu, który jest zawsze ustawiony na 1, więc wartości w znaczeniu są zawsze między [0,5, 1). Pozwala to tym platformom przechowywać wartości z nieco większą precyzją (więcej na ten temat poniżej). Mój przykład tego nie robi.

Nasza wartość 3,14159 byłaby reprezentowana jako coś w rodzaju

    0 10000010 11001001000011111100111
    ^ ^ ^
    | | |
    | | + --- znaczenie = 0,7853975 ...
    | |
    | + ------------------- wykładnik = 2 (130-128)
    |
    + ------------------------- znak = 0 (dodatni)

    wartość = -1 (znak) * 2 (wykładnik) * (znaczenie)
    wartość = -1 0 * 2 2 * 0,7853975 ...
    wartość = 3,14159 ...

Coś, co zauważysz, jeśli dodasz wszystkie bity w znaczeniu, to to, że nie sumują się one 0,7853975; faktycznie wychodzą na 0.78539747. Nie ma dość bitów, aby dokładnie zapisać wartość ; możemy przechowywać tylko przybliżenie. Liczba bitów w znaczeniu określa precyzję lub liczbę cyfr znaczących, które można zapisać. 23 bity dają nam około 6 cyfr dziesiętnych precyzji. 64-bitowe typy zmiennoprzecinkowe oferują wystarczającą liczbę bitów i dają około 12 do 15 cyfr precyzji. Należy jednak pamiętać, że istnieją wartości, których nie można dokładnie przedstawić bez względu na sposóbwiele używanych bitów. Podobnie jak wartości takie jak 1/3 nie mogą być reprezentowane przez skończoną liczbę cyfr dziesiętnych, podobnie jak wartości 1/10 nie mogą być reprezentowane przez skończoną liczbę bitów. Ponieważ wartości są przybliżone, obliczenia z nimi również są przybliżone, a błędy zaokrąglania kumulują się.

Liczba bitów w wykładniku określa zakres (minimalne i maksymalne wartości, które możesz reprezentować). Jednak w miarę zbliżania się do wartości minimalnych i maksymalnych zwiększa się różnica między wartościami reprezentatywnymi. Oznacza to, że jeśli nie możesz dokładnie przedstawić wartości między 0,785397 a 0,785398, to nie możesz dokładnie przedstawić wartości między 7,85397 a 7,85398 albo wartości między 78,5397 a 78,5398 lub wartości między 785397.0 a 785398.0. Zachowaj ostrożność, mnożąc bardzo duże (pod względem wielkości) liczby przez bardzo małe liczby.

John Bode
źródło
„ale zamiast rezerwować kolejny bit znaku” Opisujesz dokładnie zachowanie podpisanej liczby całkowitej.
Simon
6

W .ogóle nie jest przechowywany. Po pierwsze, powinieneś zrozumieć notację inżynierską, która ma współczynnik stałej precyzji i wykładnik liczb całkowitych: 1wynosi 1,0 · 10 0 = 1.0E0, 2 to 2.0E0, 10 to 1.0E1itd. Pozwala to na bardzo krótkie notowanie dużych liczb. Miliard to 1.0E9. Współczynnik zanim Ezwykle zapisaną w postaci liczby stałej precyzji: 1.00000E9. Wynika to z tego, że jeden miliard jeden i jeden = 1 000 000 001 i jeden miliard są takie same w tym zapisie, gdy precyzja nie jest wystarczająco duża. Pamiętaj również, że czynnik nigdy nie potrzebuje wiodącego zera. Zamiast tego wykładnik potęgi można zmniejszać, dopóki tak się nie stanie.

W pamięci liczba zmiennoprzecinkowa jest reprezentowana podobnie: jeden bit ma znak, niektóre bity tworzą współczynnik jako liczba o stałej precyzji („mantysa”), pozostałe bity tworzą wykładnik wykładniczy. Istotne różnice w notacji inżynierskiej podstawy 10 polegają na tym, że wykładnik ma teraz podstawę 2. Dokładny rozmiar każdej części zależy od dokładnego standardu zmiennoprzecinkowego, którego używasz.

amon
źródło
3
To jest „notacja naukowa”. „Notacja inżynierska” ma miejsce, gdy wykładnik jest ograniczony do wielokrotności 3.
Clement J.
7
Wykorzystanie bazy 2 jest bardzo ważne. Określa, które wartości mogą być przechowywane dokładnie, a które nie, a nawet jeśli nie masz kłopotów z opracowaniem intuicji, dla której wartości (wiem, że nie mogę), powinieneś przynajmniej pamiętać, że cyfry dziesiętne są całkowicie bezużyteczne sposób myślenia o pływakach.
1
@delnan: Jeśli to pomaga, każdy bit w mantysie jest o połowę wyższy od bitu. Tak więc zmiennoprzecinkowe mogą przechowywać sumy ujemnych mocy dwóch: 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128 i tak dalej, do granicy mantysy . Zatem epsilon w wersji 32-bitowej floatwynosi 2^-22 * exponentokoło 1/4194304.
greyfade