[c++] [selfmade] float zu string konvertieren
Verfasst: 19.11.2017, 14:26
Hallo.
Ich versuche gerade einen float in einen string umzuwandeln. Zum Experimentieren und mein Problem besser darzustellen, habe ich folgendes gemacht:
Mein Probleme scheinen nur die "Überläufe" zu sein. Gäbe es einen __int128 oder für double einen __int256, hätte ich vermutlich kein Problem.
Wie ich aus einer Ganzzahl/int einen string erzeuge, stellt kein Problem dar. Mein Problem liegt nur bei hohen Exponenten.
Ich habe ein wenig sprintf_s debuggt, und dort scheint man auch, nachdem man erstmal den "Template-Terror" hinter sich hat, eine besonders große Ganzzahl (big_integer) zu nutzen. Vielleicht sollte ich eine Klasse für besonders große Ganzzahlen programmieren und damit meine Probleme lösen?
Ich versuche gerade einen float in einen string umzuwandeln. Zum Experimentieren und mein Problem besser darzustellen, habe ich folgendes gemacht:
Code: Alles auswählen
int FloatToStringTest(void)
{
struct StructFloat32
{
unsigned int Mantissa : 23;
unsigned int Exponent : 8;
unsigned int Sign : 1;
};
union UnionFloat32
{
float Value;
StructFloat32 Struct;
};
UnionFloat32 Test;
Test.Value = 234.435f;
unsigned int Mantissa = Test.Struct.Mantissa + 0x00800000;
char Exponent = Test.Struct.Exponent - 127;
char Sign = Test.Struct.Sign;
if (128 == Exponent)
{
if (0 == Mantissa)
{
if (0 == Sign)
{
// Infinity
}
else
{
// -Infinity
}
}
else
{
// NaN
}
return 0;
}
if (Exponent >= 23)
{
// Problem 1: Überlauf möglich
unsigned __int64 Integer = Mantissa;
Integer <<= (Exponent - 23); // Überlauf möglich
return 0;
}
else if (Exponent >= 0)
{
// Sollte immer funktionieren?
unsigned char Shift = 23 - Exponent;
unsigned __int64 Integer = Mantissa >> Shift;
unsigned __int64 Fraction = Mantissa - (Integer << Shift);
unsigned __int64 Divisor = 1ULL << Shift;
unsigned __int64 Precision = 1000000000;
unsigned __int64 Float = (Fraction + Divisor) * Precision / Divisor;
float Check = Fraction / (float)Divisor;
return 0;
}
else
{
// Problem 2: Überlauf möglich
unsigned char Shift = 23 - Exponent;
Shift = 63;
unsigned __int64 Fraction = Mantissa;
unsigned __int64 Divisor = 1ULL << Shift; // Shift > 63 = Überlauf
unsigned __int64 Precision = 1000000000;
unsigned __int64 Float = (Fraction + Divisor) * Precision / Divisor; // Überlauf möglich
float Check = Fraction / (float)Divisor;
return 0;
}
}
Wie ich aus einer Ganzzahl/int einen string erzeuge, stellt kein Problem dar. Mein Problem liegt nur bei hohen Exponenten.
Ich habe ein wenig sprintf_s debuggt, und dort scheint man auch, nachdem man erstmal den "Template-Terror" hinter sich hat, eine besonders große Ganzzahl (big_integer) zu nutzen. Vielleicht sollte ich eine Klasse für besonders große Ganzzahlen programmieren und damit meine Probleme lösen?