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?


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.


„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.


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
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.