2013-07-30 14 views
5

Dla aplikacji C, którą implementuję, potrzebuję móc odczytać i zapisać zestaw wartości konfiguracyjnych do pliku. Te wartości są liczbami zmiennoprzecinkowymi. W przyszłości jest możliwe, że inna aplikacja (może być napisana w C++, Pythonie, Perlu, itp.) Użyje tych samych danych, więc te wartości konfiguracyjne muszą być przechowywane w dobrze zdefiniowanym formacie, który jest niezależny od kompilatora i maszyny .Przechowywanie liczb zmiennoprzecinkowych w pliku

Do konwersji endianizmu można użyć funkcji konwersji kolejności bajtów (ntoh/hton), ale jaki jest najlepszy sposób na obejście różnych znaczeń wartości "zmiennoprzecinkowych"? Czy istnieje typowa metoda przechowywania float? Zaokrąglanie i obcinanie nie stanowi problemu, tak długo, jak jest zdefiniowane.

+2

Najlepszy sposób przechowywania wartości zmiennoprzecinkowej (lub dowolnej wartości), niezależnej od platformy, jest w formie tekstowej. Przechowywanie w formie binarnej nie będzie działać, a korzystanie z funkcji endianess nie pomoże, ponieważ nie ma zdefiniowanej dla binarnych reprezentacji wartości zmiennoprzecinkowych. –

+2

@JoachimPileborg Chociaż może nie być standardowej zdefiniowanej endianness dla binarnych reprezentacji zmiennoprzecinkowych, łatwo wymusić je samemu. Wszystko, co musisz zrobić, to dekretować, że wartości zmiennoprzecinkowe są przechowywane w, powiedzmy, dużym formacie endian. –

+0

Możesz użyć standardowego typu, takiego jak IEEE754 podwaja – SheetJS

Odpowiedz

5

Istnieją prawdopodobnie dwa główne warianty:

  1. przechowywać w formacie tekstowym. W tym przypadku standaryzowałbyś w określonym formacie, używając dobrze zdefiniowanego separatora dziesiętnego i używałbyś notacji naukowej, tj. 6.66e42.
  2. Przechowuj w formacie binarnym, używając standardu IEEE754. Użyj 4 lub 8 bajtowego typu danych. I jak zauważyłeś, musiałbyś zadowolić się konwencją endiancką.

Format tekstowy jest prawdopodobnie bardziej przenośny, ponieważ istnieją maszyny, które nie znają natywnie standardu IEEE754. Powiedział, że takie maszyny są rzadkie w tych czasach.

+0

Dlaczego warto używać liczby dziesiętnej? –

+0

@Eric Dla przenośności i czytelności ludzkiej –

+2

Decimal nie daje możliwości przenoszenia, ponieważ właściwa konwersja między liczbami dziesiętnymi a binarnymi zmiennoprzecinkami nie jest tak dobrze obsługiwana, jak powinna. Większość standardów językowych nie wymaga poprawnie zaokrąglonych konwersji, a różne implementacje ich nie gwarantują. Natomiast heksadecymalnie można łatwo przekonwertować, nawet jeśli trzeba napisać własną procedurę konwersji. –

0

IEEE 754 lub ISO/IEC/IEEE 60559: 2011, jest standardem dla zmiennoprzecinkowej używanej przez większość języków.

Dla C jest oficjalnie brany standardowo przez C11. (Załącznik F C11 IEC 60559 zmiennoprzecinkowych arytmetyczną)

+0

Załącznik F jest opcjonalny; implementacja musi tylko być zgodna z nią, jeśli definiuje '__STDC_IEC_559__'. –

0

W przypadku małych ilości danych, takich jak wartości konfiguracyjne, należy użyć tekstu, który nie jest binarny. Jeśli chcesz, przejdź do tekstu strukturalnego o pewnej formie, na przykład JSON, XML. Zadecyduj, ile cyfr ma pisać, aby reprezentować liczbę zmiennoprzecinkową zgodnie z Twoimi wymaganiami.

Wraz ze wzrostem zakresu wymaganej przenośności (w różnych językach, systemach operacyjnych, czasie, przestrzeni itp.) Siła argumentu na korzyść tekstu staje się silniejsza.

4

Funkcje wejścia/wyjścia w formacie C mają specyfikator formatu, %a. Formatuje liczbę zmiennoprzecinkową w szesnastkowym formacie zmiennoprzecinkowym, [-] 0x h. hhhh p ± d. Oznacza to, że w razie potrzeby ma znak "-", cyfry szesnastkowe dla części ułamka, w tym punkt bazowy, "p" (dla "mocy"), aby uruchomić wykładnik i wykładnik potęgowy dwóch (dziesiętnie).

Dopóki implementacja C wykorzystuje binarny zmiennoprzecinkowy (lub dowolny zmiennoprzecinkowy taki, że jego FLT_RADIX jest potęgą dwóch), konwersja z formatem %a powinna być dokładna.

+0

Jak taki tekst byłby czytany przez języki inne niż C? –

+1

@DavidHeffernan: Szesnastkowy format zmiennoprzecinkowy można łatwo przekonwertować do binarnego zmiennoprzecinkowego i od niego. Podczas konwersji liczb pochodzących z tego samego formatu binarnego (stąd nie ma dodatkowych cyfr, które należy zaokrąglić), nie ma problemów z zaokrąglaniem. –

+0

Ale może nie być trywialne w językach innych niż C. Na przykład, jaki byłby kod, aby to zrobić w Perlu? Czy jest to funkcja wbudowana? Podejrzewam, że w przypadku wielu języków trzeba będzie wykonać własne. Dlatego ludzie mogą wybrać wygodę dziesiętną kosztem pewnej straty w ruchu w obie strony. –

Powiązane problemy