Typy zmiennoprzecinkowe o stałym rozmiarze


92

W nagłówkach stdint.h(C99), boost / cstdint.hpp i cstdint(C ++ 0x) znajduje się między innymi typ int32_t.

Czy istnieją podobne typy zmiennoprzecinkowe o stałym rozmiarze? Coś jak float32_t?


4
Dlaczego potrzebujesz czegoś takiego?
— ARAK

41
Potrzebujesz czegoś takiego, gdy masz strukturę danych z wartością zmiennoprzecinkową, a także chcesz dokładnie wiedzieć, jaki jest jej rozmiar.
— mob

5
@mobrule: Jeśli chcesz tylko wiedzieć, jaki jest rozmiar, użyj sizeofoperatora. Taki typ byłby przydatny, gdy algorytm wymaga, aby był to znany określony rozmiar.
— Stephen Canon

6
@Stephen Canon - tak, jeśli chcesz zagwarantować, jaki jest rozmiar. Powiedzmy, że instancja twojej struktury danych zmieści się w 64 bitach i może być przekazana według wartości do jakiejś zewnętrznej biblioteki.
— mob

7
@StephenCanon Rozważmy wieloplatformową bibliotekę serializacji. W jaki sposób można sizeofrozwiązać problem konsekwentnego krosowania i niesprawdzania typów pływających?
— Kyle Strand

Odpowiedzi:


47

Obecnie nic takiego nie istnieje w standardach C lub C ++. W rzeczywistości nie ma nawet gwarancji, że w floatogóle będzie binarnym formatem zmiennoprzecinkowym.

Niektóre kompilatory gwarantują, że floattypem będzie 32-bitowy format binarny IEEE-754. Niektórzy nie. W rzeczywistości floatjest to w rzeczywistości singletyp IEEE-754 na większości platform niezintegrowanych, chociaż mają zastosowanie zwykłe zastrzeżenia dotyczące niektórych kompilatorów oceniających wyrażenia w szerszym formacie.

Istnieje grupa robocza omawiająca dodanie powiązań języka C w wersji 2008 IEEE-754, która mogłaby rozważyć zalecenie dodania takiego typu. Gdyby to zostało dodane do C, spodziewam się, że standard C ++ pójdzie w ich ślady ... w końcu.


3
Niezależnie od IEEE-754 czy nie, nadal nie zapobiegnie to problemom z przenośnością Endian.
— Mark B

1
@Pietro: zmiana języka nie wpłynie na zgodność sprzętu, a jedynie wykluczy zgodność niektórych urządzeń. W jaki sposób IEEE FP gwarantuje przenośność?
— Potatoswatter

1
@Potatoswatter: Zachęciłoby to dostawców sprzętu do dostarczania zgodnych rozwiązań. Jeśli część a obsługuje standardowe C bez konieczności stosowania hacków biblioteki soft-float, a część b nie, to jest to przewaga rynkowa dla części a.
— Stephen Canon

2
@Potatoswatter: (Prawie) nikt nie dba o szybkość sprzętu. Dbamy o szybkość działania oprogramowania na sprzęcie. Oprogramowanie może być szybsze, jeśli sprzęt, na którym działa, jest zgodny ze standardami, a oprogramowanie nie musi wykrywać i naprawiać 15 różnych przypadków specjalnych, w zależności od platformy, na której jest uruchomione.
— Stephen Canon

8
Jak, u licha, można uzyskać lepszą przenośność, zapobiegając kompilacji kodu na wielu niszowych architekturach? Albo polegasz na elementach pływających będących IEEE, w którym to przypadku twój kod będzie już działał w każdej implementacji zgodnej z IEEE i na niczym innym, albo nie, w takim przypadku twój kod będzie działał w szerszym zakresie systemów. Gdyby C ++ gwarantował zgodność ze standardem IEEE, Twój kod w magiczny sposób nie stałby się bardziej przenośny, po prostu wykluczyłbyś, że mógłby kiedykolwiek działać na tych niezgodnych architekturach. Twoja logika jest całkowicie wsteczna.
— jalf

30

Jeśli chcesz wiedzieć, czy floatjest to 32-bitowy typ IEEE, sprawdź std::numeric_limits<float>::is_iec559. To stała czasu kompilacji, a nie funkcja.

Jeśli chcesz być bardziej kuloodporny, sprawdź również, czy std::numeric_limits<float>::digitsnie podstępnie używają standardu podwójnej precyzji IEEE dla float. Powinno być 24.

Jeśli chodzi o long doubleto, ważniejsze jest sprawdzenie, digitsponieważ istnieje kilka formatów IEEE, którymi może być: 128 bitów (cyfry = 113) lub 80 bitów (cyfry = 64).

Nie byłoby to praktyczne float32_t, ponieważ zwykle chcesz używać sprzętu zmiennoprzecinkowego, jeśli jest dostępny, i nie polegać na implementacji oprogramowania.


long doubleFormat na OS X (zarówno 32-bit i 64-bit Intel) jest dokładnie IEEE-754 podwójny format rozszerzony przechowywane w ostrokońcej kolejności. Nie ma w tym nic dziwnego. Bajty 0-7 zawierają pole istotności, a bajty 8 i 9 zawierają wykładnik i pola znaku.
— Stephen Canon

@Stephen: to dobra wiadomość: v). Czy zgadza się to z opublikowanymi przeze mnie liczbami?
— Potatoswatter

1
Pamiętaj, że podwójnie rozszerzone (w przeciwieństwie do innych formatów 754) ma wyraźne znaczenie wiodące, więc 5.0Lma znaczenie a000000000000000. Jego nieobciążony wykładnik wynosi +2, a podwójny rozszerzony wykładnik wynosi 3fff, więc obciążony wykładnik dla 5,0L wynosi 4001. Rzeczywisty wzorzec bajtów przechowywany w kolejności little-endian to 00 00 00 00 00 00 00 a0 01 40, a jeśli zobaczysz to jako dwie 64-bitowe liczby całkowite little-endian, zobaczysz dokładnie to, co zaobserwowałeś.
— Stephen Canon,

(*) podwójnie rozszerzony, jak zaimplementowano sprzętowo przez firmę Intel, to znaczy. Podwójnie rozszerzony format nie jest w rzeczywistości przypięty tak, jak pozostałe dwa podstawowe formaty IEEE-754 (1985).
— Stephen Canon

@Stephen: Jestem prawie pewien, że 4001w little-endian jest 01 40 00 00 ...Jeśli nic innego, najmniej znaczący bajt jest pierwszy. Spodziewam się, że sekwencja a0 01 40pojawi się gdzieś w numerze (jeśli wykonali tylko rotację), ale nie sądzę, że wyjaśniłeś dlaczego a0i 01 40jesteś w całkowicie oddzielnych połówkach.
— Potatoswatter

18

Jeśli uważasz, że posiadanie takich typów jak float32_t i float64_t jest niepraktyczne z jakichkolwiek powodów, musisz być zbyt przyzwyczajony do swojego znajomego systemu operacyjnego, kompilatora, że ​​nie możesz zbytnio wyjrzeć poza swoje małe gniazdo.

Istnieje sprzęt, który natywnie obsługuje 32-bitowe operacje zmiennoprzecinkowe IEEE i inne, które wykonują 64-bitowe. Czasami takie systemy muszą nawet ze sobą rozmawiać, w takim przypadku niezwykle ważne jest, aby wiedzieć, czy double jest 32-bitowy, czy 64-bitowy na każdej platformie. Jeśli platforma 32-bitowa miałaby wykonywać nadmierne obliczenia w oparciu o wartości 64-bitowe z drugiej, możemy chcieć rzucić na niższą precyzję w zależności od wymagań dotyczących czasu i prędkości.

Osobiście czuję się nieswojo używając pływaków i podwójnych, chyba że wiem dokładnie, ile bitów znajduje się na mojej platformie. Tym bardziej, jeśli mam je przenieść na inną platformę przez jakiś kanał komunikacyjny.


„Osobiście czuję się nieswojo używając pływaków i podwójnych, chyba że wiem dokładnie, ile bitów znajduje się na mojej platformie. Tym bardziej, jeśli mam przenieść je na inną platformę przez jakiś kanał komunikacyjny”. - Masz na myśli, że używasz formatów plików tekstowych? Z nimi wynika wada rozmiaru pliku: 32 zmiennoprzecinkowy wymaga 4 bajtów; te w formie tekstowej mogą przedstawiać tylko czterocyfrową liczbę ...
— Pietro

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.