Często w moim doświadczeniu programistycznym muszę podjąć decyzję, czy powinienem używać wartości float, czy double. liczby. Czasami stawiam na float, czasami na podwójny, ale tak naprawdę jest to bardziej subiektywne. Gdybym stanął w obliczu obrony swojej decyzji, prawdopodobnie nie podałbym rozsądnych powodów.

Kiedy używasz float, a kiedy double? Czy zawsze używasz double, tylko wtedy, gdy występują ograniczenia pamięci, wybierasz float? Lub używasz zawsze zmiennoprzecinkowego, chyba że wymaganie precyzji wymaga użycia double? Czy są jakieś zasadnicze różnice w zakresie złożoności obliczeniowej podstawowych arytematów między zmiennoprzecinkowymi i podwójnymi? Jakie są zalety i wady używania float lub double? A czy użyłeś nawet długiego znaku podwójnego?

Komentarze

  • W wielu przypadkach nie chcesz używać żadnego, ale raczej dziesiętnego typu zmiennoprzecinkowego lub stałego. Binarne typy zmiennoprzecinkowe mogą ' dokładnie odzwierciedlać większość liczb dziesiętnych.
  • Powiązane z Co powoduje błędy zaokrągleń zmiennoprzecinkowych ? . @CodesInChaos moja odpowiedź sugeruje zasoby, które pomogą Ci to ustalić, nie ma rozwiązania jednego rozmiaru dla wszystkich .
  • Co dokładnie rozumiesz przez ” ułamki dziesiętne „. Jeśli chcesz dokładnie przedstawić wartości takie jak 0,01 (powiedzmy dla pieniędzy), to (binarna) zmiennoprzecinkowa nie jest odpowiedzią. Jeśli chodzi o liczby nie będące liczbami całkowitymi, to prawdopodobnie liczba zmiennoprzecinkowa jest w porządku – ale wtedy ” dziesiętne ” nie jest najlepszym słowem aby opisać to, czego potrzebujesz.
  • Biorąc pod uwagę (na dzień dzisiejszy) większość kart graficznych akceptuje zmiennoprzecinkowe nad podwójnymi, programowanie graficzne często używa pojedynczej precyzji.
  • Nie ' t zawsze mam wybór. Na przykład na platformie Arduino zarówno podwójne, jak i zmiennoprzecinkowe są równoważne pływaniu. Musisz znaleźć bibliotekę dodatków, aby obsłużyć prawdziwe dublety.

Odpowiedź

Domyślny wybór dla Typ zmiennoprzecinkowy powinien być double. Jest to również typ, który otrzymujesz w przypadku literałów zmiennoprzecinkowych bez sufiksu lub (w języku C) standardowych funkcji, które działają na liczbach zmiennoprzecinkowych (np. exp, sin itp.).

float powinno być używane tylko wtedy, gdy musisz operować na wielu liczbach zmiennoprzecinkowych (pomyśl rzędu tysięcy lub więcej), a analiza algorytmu wykazała, że zmniejszony zakres i dokładność nie stanowią problemu.

long double można użyć, jeśli potrzebujesz większego zakresu lub dokładności niż double, a jeśli zapewnia to na Twojej platformie docelowej.

Podsumowując, float i long double powinny być zarezerwowane do użytku przez specjalistów, a double do użytku „na co dzień”.

Komentarze

  • Prawdopodobnie nie rozważałbym liczby zmiennoprzecinkowej dla kilku tysięcy wartości, chyba że wystąpiłby problem z wydajnością związany z pamięcią podręczną zmiennoprzecinkową g i przenoszenia danych. Zazwyczaj analiza pokazująca, że zmiennoprzecinkowa jest wystarczająco dokładna, wiąże się ze znacznymi kosztami.
  • Jako dodatek, jeśli potrzebujesz zgodności z innymi systemami, korzystne może być użycie tych samych typów danych.
  • I ' d używam liczb zmiennoprzecinkowych dla milionów liczb, a nie tysięcy. Ponadto niektóre GPU radzą sobie lepiej z pływakami, w tym specjalistycznym przypadku używają pływaków. W przeciwnym razie, jak mówisz, użyj podwójnych.
  • @PatriciaShanahan – ' problem z wydajnością związany z … ' A dobrym przykładem jest, jeśli planujesz użyć instrukcji SSE2 lub podobnych instrukcji wektorowych, możesz wykonać 4 operacje / wektor w trybie zmiennoprzecinkowym (w porównaniu z 2 na podwójny), co może dać znaczną poprawę szybkości (o połowę mniej operacji io połowę mniej danych do odczytania & napisz). Może to znacznie obniżyć próg, w którym używanie zmiennoprzecinkowych staje się atrakcyjne i warte wysiłku, aby rozwiązać problemy numeryczne.
  • Popieram tę odpowiedź jedną dodatkową radą: gdy używa się wartości RGB do wyświetlania, dopuszczalne jest użycie float (i czasami z połowiczną precyzją), ponieważ ani ludzkie oko, ani ekran, ani system kolorów nie mają tak wielu bitów precyzji. Ta rada dotyczy, powiedzmy, OpenGL itp. Ta dodatkowa porada nie dotyczy obrazów medycznych, które mają bardziej rygorystyczne wymagania dotyczące dokładności.

Odpowiedź

Rzadko zdarza się, że używa się float zamiast podwójnego w kodzie skierowanym na nowoczesne komputery. Dodatkowa precyzja zmniejsza (ale nie eliminuje) ryzyko zaokrągleń lub innych niedokładności powodujących problemy.

Główne powody, dla których przychodzi mi do głowy użycie float to:

  1. Przechowujesz duże tablice liczb i potrzebujesz zmniejszyć zużycie pamięci programu.
  2. Celujesz w system, który natywnie nie obsługuje zmiennoprzecinkowych podwójnej precyzji. Do niedawna wiele kart graficznych obsługiwało tylko zmiennoprzecinkowe pojedynczej precyzji. Jestem pewien, że istnieje wiele energooszczędnych i wbudowanych procesorów, które również mają ograniczoną obsługę zmiennoprzecinkowych.
  3. Celujesz w sprzęt, w którym pojedyncza precyzja jest szybsza niż podwójna precyzja, a aplikacja jest intensywnie używana arytmetyki zmiennoprzecinkowej Na nowoczesnych procesorach Intela uważam, że wszystkie obliczenia zmiennoprzecinkowe są wykonywane z podwójną precyzją, więc nic tu nie zyskasz.
  4. Przeprowadzasz optymalizację na niskim poziomie, na przykład używając specjalnych instrukcji procesora, które działają na wielu liczbach naraz.

Tak więc idź, chyba że masz ograniczenia sprzętowe lub jeśli analiza nie wykazała, że przechowywanie liczb o podwójnej precyzji znacząco wpływa na zużycie pamięci.

Komentarze

  • ” Nowoczesne komputery ” czyli procesory Intel x86. Niektóre maszyny używane przez starożytnych zapewniały doskonałą precyzję z podstawowym typem spławika. (CDC 6600 używał 60-bitowego słowa, 48 bitów znormalizowanej mantysy zmiennoprzecinkowej, 12 bitów wykładnika. To ' jest PRAWIE tym, co daje x86 dla podwójnej precyzji).
  • @ John.R.Strohm: zgodził się, ale kompilatory C nie istniały na CDC6600. To był Fortran IV …
  • Przez ” nowoczesne komputery ” mam na myśli każdy procesor zbudowany w ostatniej dekadzie lub dwa, a właściwie, ponieważ standard zmiennoprzecinkowy IEEE został szeroko zaimplementowany. ' doskonale zdaję sobie sprawę, że istnieją architektury inne niż x86 i miałem to na uwadze w mojej odpowiedzi – wspomniałem o GPU i wbudowanych procesorach, które zazwyczaj nie są x86.
  • To ' jest po prostu nieprawdą. SSE2 może manipulować 4 pływakami lub 2 podwójnymi w jednej operacji, AVX może manipulować 8 pływakami lub 4 podwójnymi, AVX-512 może manipulować 16 pływakami lub 8 podwójnymi. W przypadku każdego rodzaju obliczeń o wysokiej wydajności matematyka na liczbach zmiennoprzecinkowych powinna być traktowana jako dwukrotnie szybsza od tych samych operacji na podwójnych operacjach na procesorach x86.
  • I ' s nawet gorzej, ponieważ w pamięci podręcznej procesora można zmieścić dwa razy więcej elementów zmiennoprzecinkowych niż w przypadku podwojów, a opóźnienie pamięci prawdopodobnie będzie głównym wąskim gardłem w wielu programach. Utrzymywanie ciepłego zestawu roboczego pływaków w pamięci podręcznej może być dosłownie o rząd wielkości szybsze niż używanie podwójnych i przenoszenie ich do pamięci RAM.

Odpowiedź

Użyj double do wszystkich obliczeń i zmiennych tymczasowych. Użyj float, gdy chcesz zachować tablicę liczb – float[] (jeśli precyzja jest wystarczająca) i masz do czynienia z ponad dziesiątkami tysiące float liczb.

Wiele / większość funkcji lub operatorów matematycznych konwertuje / zwraca double, a Ty nie ” t chcesz rzutować liczby z powrotem do float dla jakichkolwiek pośrednich kroków.

Np. jeśli masz wpisane 100 000 liczb z pliku lub strumienia i musisz posortuj je, umieść liczby w float[].

Odpowiedź

Niektóre platformy (ARM Cortex-M2, Cortex-M4 itp.) Nie obsługują double (zawsze można to sprawdzić w instrukcji obsługi do procesora. Jeśli nie ma ostrzeżeń ani błędów kompilacji, nie oznacza to, że kod jest optymalny. Można emulować double .). Dlatego może być konieczne trzymanie się int lub float .

Jeśli tak nie jest, użyłbym double .

Możesz zapoznać się ze słynnym artykułem D. Goldberga („Co każdy informatyk powinien wiedzieć o arytmetyce zmiennoprzecinkowej”). Powinieneś pomyśleć dwa razy przed użyciem arytmetyki zmiennoprzecinkowej. Istnieje duża szansa, że nie są one wcale potrzebne w twojej konkretnej sytuacji.

http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf

Komentarze

  • Odpowiedź na to pytanie była już całkiem dobra rok temu …ale w każdym razie ' d mówię za każdym razem, gdy ' używasz double na platformach z przyspieszeniem FPU o podwójnej precyzji, powinieneś używać na jakimkolwiek innym, nawet jeśli oznacza to pozwolenie kompilatorowi na emulowanie go zamiast korzystania z FPU tylko z zmiennoprzecinkowym (zauważ, że FPU ' s aren ' t również wymagane na wszystkich platformach, w rzeczywistości architektura Cortex-M4 definiuje je jako funkcję opcjonalną [czy M2 była literówką?]).
  • Kluczem do tej logiki jest, podczas gdy to ' to prawda, że należy mieć dość arytmetyki zmiennoprzecinkowej, a ' jest wiele ” dziwactwa „, zdecydowanie nie przyjmując obecności obsługi FPU dla dubletów, aby oznaczać po prostu używanie podwójnych zamiast pływaków. Pływaki są generalnie szybsze niż podwójne i zajmują mniej pamięci (funkcje FPU są różne). Wielkość użycia wyklucza przedwczesną optymalizację tego punktu. Podobnie jak fakt, że podwojenie są ewidentnie przesadą w przypadku wielu (może nawet większości) zastosowań. Czy elementy na tej stronie naprawdę muszą mieć swoje względne pozycje i rozmiary obliczone z 13 miejscami po przecinku?
  • W przypadku dołączania linku do strony lub dokumentu znajdującego się poza witryną, skopiuj istotne informacje lub podsumowanie z dokumentu do odpowiedzi. Linki poza witryną mają tendencję do zanikania z czasem.

Odpowiedź

W przypadku problemów w świecie rzeczywistym próg próbkowania wynosi Twoje dane są ważne, gdy odpowiadasz na to pytanie. Podobnie ważna jest również podłoga szumowa. Jeśli któryś z nich zostanie przekroczony przez wybrany typ danych, zwiększenie precyzji nie przyniesie żadnych korzyści.

Większość rzeczywistych samplerów jest ograniczona do 24-bitowych przetworników cyfrowo-analogowych. Sugerowanie, że 32 bity precyzji w obliczeniach w świecie rzeczywistym powinny być odpowiednie, gdy istotna jest precyzja 24 bity.

Podwójna precyzja kosztuje 2x pamięć. Dlatego ograniczenie użycia podwójnych liczb zmiennoprzecinkowych może drastycznie zmniejszyć zużycie pamięci / przepustowość uruchomionych aplikacji.

Odpowiedź

Wybór jaka zmienna zostanie użyta między float a double zależy od dokładności wymaganych danych. Jeśli od odpowiedzi wymagana jest nieznaczna różnica w stosunku do rzeczywistej odpowiedzi, wymagana liczba miejsc dziesiętnych będzie wiele, a zatem będzie narzucać użycie tego podwójnego. Funkcja Float odetnie część miejsc dziesiętnych, zmniejszając w ten sposób dokładność.

Komentarze

  • Ta odpowiedź nie ' nie dodaje nic nowego do pytania i nie mówi nic o rzeczywistym zastosowaniu.

Odpowiedź

Zwykle używam typu float, gdy Nie potrzebuję dużej precyzji – na przykład w przypadku pieniędzy – co jest złe, ale przywykłem do tego, aby źle postępować.

Z drugiej strony używam double kiedy potrzebuję większej precyzji, na przykład w przypadku złożonych algorytmów matematycznych.

Standard C99 mówi tak:

Istnieją trzy typy zmiennoprzecinkowe: zmiennoprzecinkowe, podwójne i długie podwójne. Typ double zapewnia co najmniej taką samą precyzję jak zmiennoprzecinkowy, a typ long double zapewnia co najmniej taką samą precyzję jak double. Zbiór wartości typu float jest podzbiorem zbioru wartości typu double; zbiór wartości typu double jest podzbiorem zbioru wartości typu long double.

Tak naprawdę nigdy nie używałem long double, ale nie używam C / C ++ tak często. Zwykle używam języków dynamicznie typowanych, takich jak Python, gdzie nie trzeba się przejmować typami.

Więcej informacji na temat Double vs Float można znaleźć w pytaniu w SO .

Komentarze

  • Używanie zmiennoprzecinkowych do poważnych obliczeń finansowych jest prawdopodobnie błędem.
  • float jest dokładnie niewłaściwym typem dla pieniędzy. Musisz używać najwyższej możliwej precyzji.
  • @BartvanIngenSchenau Zmiennoprzecinkowy dla pieniędzy jest zwykle w porządku, binarny zmiennoprzecinkowy nie. Na przykład .net ' s Decimal jest typem zmiennoprzecinkowym i zwykle jest ' dobry wybór do obliczeń pieniężnych.
  • @ChrisF Nie ' nie potrzebujesz ” wysokiej precyzji ” dla pieniędzy, potrzebujesz dokładnych wartości.
  • @SeanMcSomething – Słuszna uwaga. Jednak liczby zmiennoprzecinkowe są nadal niewłaściwego typu i biorąc pod uwagę typy zmiennoprzecinkowe dostępne w większości języków, potrzebujesz ” wysokiej precyzji „, aby uzyskać ” dokładne wartości „.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *