Zapis bitów liczby typu float do pliku

0

Witam
W jaki sposób można zapisać bity liczby typu float do pliku?
Chodzi mi o zapis np. liczby 0.21f jako bitów mantysy i cechy.
Próbowałem zrobić to na tej zasadzie, jednak ta funkcja obsługuje tylko liczby całkowite:

int X;
//float I = 0.254f; Błąd
int I = 2554;

X = 0;

for (unsigned short int TB_02 = 0; TB_02 < 32; TB_02++) if(I&(1<<TB_02)) X|=(1<<TB_02);

Czy istnieje funkcja, która pozwala w szybki sposób odczytać wartość poszczególnych bitów liczby typu float?

0

O to chodzi?:

float _I = 0.254f;
int I = *(int*) &_I;
0

Dziękuję za pomoc, funkcja write rozwiązała problem.

0

to co tutaj robisz to jest UB. Nazwy zaczynające się od podłogaWIELKALITERA są zarezerwowane dla implementacji. Odnoszenie się do danych za poprzez wskaźnik do innego typu, poza specjalnymi przypadkami, jest zabronione.

O tym, że nie może używać wielkich liter po podłodze, to nie wiedziałem, ale z drugim się nie zgodzę, bo jest to powszechnie spotykanie w C. Można by było jedynie użyć int32_t zamiast int.

2

Zawsze można użyć takiego badziewia, owszem w teorii to też UB ale jak na razie nie znalazłem żadnego przypadku kiedy nie zadziała jak trzeba:

union FloatBits
  {
   float F;
   unsigned char U[sizeof(float)];
  };

FloatBits FB;
FB.F=6.66;
for(int i=0;i<sizeof(float);++i) cout<<setfill('0')<<setw(2)<<hex<<FB.U[i];

Należy pamiętać że wynik może być różny w systemach BigEndian i LittleEndian.
No i oczywiście należy pamiętać iż standard nie definiuje dokładnego formatu zmiennych typu float, czyli może się być zupełnie czymś innym w jakimś innym systemie.

4
bywalec napisał(a):

to co tutaj robisz to jest UB. Nazwy zaczynające się od podłogaWIELKALITERA są zarezerwowane dla implementacji. Odnoszenie się do danych za poprzez wskaźnik do innego typu, poza specjalnymi przypadkami, jest zabronione.

O tym, że nie może używać wielkich liter po podłodze, to nie wiedziałem, ale z drugim się nie zgodzę, bo jest to powszechnie spotykanie w C. Można by było jedynie użyć int32_t zamiast int.

Możesz się nie zgadzać ile chcesz, to nic nie zmienia.

Standard C++ (n3797), §3.10/10 napisał(a)

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
— the dynamic type of the object,
— a cv-qualified version of the dynamic type of the object,
— a type similar (as defined in 4.4) to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
— an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
— a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
— a char or unsigned char type.
§4.4 odnosi się do zmiany kwalifikatorów (const/volatile)

Pomimo, że wątek ma w tagu c++, sprawdziłem też jak sprawa wygląda w C:

Standard C (n1570), §6.5/7 napisał(a)

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the object,
— a type that is the signed or unsigned type corresponding to the effective type of the object,
— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
— a character type.

Inaczej mówiąc, sam fakt, że coś jest powszechnie spotykane nie czyni tego poprawnym.

2

Ja rdzę użyć jakiegoś framework'a lub bilioteki, która pilnuje by wszystko miało jednolity format bez względu na platformę/kompilator.
Przykładowo w Qt jest QDataStream, które pozwala na kontrolowanie standardu float-ów endiany itp.

0

Program będzie kompilowany tylko przy użyciu Microsoft Visual Studio 2012 oraz będzie uruchamiany tylko na systemie windows (Vista, 7, 8) 32 oraz 64 bit.
Czy taki kod jest odpowiedni:

template <typename T> void KCI_S (std::vector <T> &KCT, std::string KCA){

	std::ofstream Kplik(KCA + ".save", std::ios::out | std::ios::binary);

	for (auto &TB_01 : KCT) Kplik.write (reinterpret_cast<char*>(&TB_01), sizeof (T));

	Kplik.close();

}
template <typename T> void DCI_S (std::vector <T> &KCT, std::string KCA){
	
	char t;

	union{

		char V[sizeof (T)];
		T Var;

	};

	std::fstream Kplik(KCA + ".save", std::ios::in | std::ios::binary);

	if (Kplik.is_open()){

		while (Kplik.get (t)){ 

			V[0] = t;

			for (short int TB_01 = 1; TB_01 < sizeof (T); TB_01++) if (Kplik.get (t)) V[TB_01] = t;

			KCT.push_back (Var);

		}

		Kplik.close();

	}

}

1 użytkowników online, w tym zalogowanych: 0, gości: 1