Was sind in Unreal die Unterschiede zwischen float und FFloat32 in C ++?

17

Ich habe versucht, einige tiefere Aspekte von UE4 zu lernen, und während ich viele Beispielcodes und auch die Quellbasis der Engine las, bemerkte ich, dass manchmal Leute (und der eigentliche Quellcode) das Standard-C ++ float- Grundelement verwenden, aber manchmal die benutzerdefinierte Implementierung von UE4 verwenden FFloat32.

Dann wurde ich neugierig: Wenn ich ein Spiel mit Unreal programmiere, was sind die Unterschiede zwischen der Verwendung dieser beiden Optionen und was sind möglicherweise die Hauptfälle, in denen man das Standard-C ++ - Grundelement zugunsten der Implementierung der Engine fallen lassen sollte?

Kim Shutter
quelle
1
Ich würde gerne die Beispiele lesen, die Sie tatsächlich verwenden FFloat32.
@JoshPetrie Einige von ihnen waren offline, ein paar waren online. Sobald ich zu Hause Zeit habe, werde ich nach ihnen suchen, um sie zu teilen
Kim Shutter

Antworten:

17

floatist gut, ein C ++ - Gleitkomma. FFloat32ist eine Struktur, die einen Float sowie (über eine Vereinigung) die zerlegten Bitfelder für die Vorzeichen-, Mantissen- und Exponententeile dieses Floats darstellt.

Sie sollten im Allgemeinen nie verwenden, FFloat32außer wenn:

  • Sie verwenden eine API, die ein erwartet FFloat32(diese sind sehr selten) oder
  • Sie müssen eine Art Low-Level-Bit-Hackery mit einem Fließkomma-Wert ausführen (heutzutage auch ziemlich selten).

Es ist nicht das FFloat32ist schlecht , per se, es ist nur , dass sie nicht wirklich bieten Ihnen alles , was Sie für allgemeine Zwecke bräuchten Punkt Nutzung schweben.

Es ist weniger verbreitet als ein einfaches altes Gerät float, das geringfügige Auswirkungen auf die Lesbarkeit hat (andere wissen möglicherweise nicht sofort, wofür es gedacht ist). Es wird auch nicht implizit in konvertiert, floatsodass Sie something.FloatValueviel tippen, was ebenfalls keine große Sache ist, aber langweilig werden kann.

Schließlich ist die Verwendung von Gewerkschaften und Bitfeldern nicht portierbar und von der Implementierung abhängig (siehe unten). Dies ist nicht Ihr Problem. Es ist Aufgabe von Epic, sicherzustellen, dass der Typ so strukturiert ist, dass er für alle unterstützten Implementierungen verwendet werden kann. Es kann jedoch zu Fehlern kommen, wenn bei einem neuen Compiler kein Problem mit der Implementierung des Typs festgestellt wird Version wird freigegeben oder zur Liste der unterstützten Compiler hinzugefügt.

Wenn Sie also nicht mit den einzelnen Bits in der Gleitkommadarstellung spielen müssen, sollten Sie dies wahrscheinlich vermeiden FFloat32(sein Cousin FFloat16, könnte etwas nützlicher sein, da es keinen Standard-16-Bit-C ++ - Gleitkommatyp gibt).

Früher war es üblich, Floats über ganzzahlige Darstellungen ihrer Komponenten für " Geschwindigkeit " zu manipulieren . Moderne Computer machen viele Plattformen überflüssig, und die verschiedenen Typ-Punning- Techniken, die verwendet werden könnten, um solche Dinge zu tun, können in jedem Fall die Leistung oder Korrektheit beeinträchtigen.

Es sollte aufschlussreich sein, dass eine Suche im GitHub-Repository von Unreal nur sehr wenige Verwendungen des FFloat32Typs aufdeckt . Alle von ihnen sind in der Definition von sich FFloat32selbst oder in der Definition von FFloat16.


Tut speziell FFloat32zwei Dinge, die der C ++ - Standard aufruft. Es:

  • Sie können so tun, als ob mehrere Gewerkschaftsmitglieder gleichzeitig aktiv wären. Es wird erwartet, dass Sie in die Gleitkomma-Member schreiben und von einem der Integer-Member lesen (9.5.1, [class.union])
  • erwartet, dass die Bitfeldzuordnung innerhalb der Vereinigung mit der der Bitzuordnung eines IEEE-Gleitkommawerts übereinstimmt; Die Zuweisung und Ausrichtung von Bitfeldelementen innerhalb eines Klassentyps ist jedoch implementierungsdefiniert (9.6.1, [class.bit]).

quelle
Unreal ist nicht in Standard-C ++ geschrieben, sondern für die speziellen Compiler, für die es geschrieben wurde. Solange sie das Erwartete tun, ist der Standard irrelevant.
user253751
Ich würde davon ausgehen, dass diese Bitfelder auch in Standard-C / C ++ durchaus portabel sind, da sie durch einen IEEE-Standard definiert sind und jeder Compiler, der ein anderes Layout für verwendet float, keine IEEE 754-konforme rote Markierung erhält (und Kompatibilitätsprobleme mit vielen vorhandenen Programmen auftreten ).
Dmitry Grigoryev
3
Das (umständliche) Problem ist, dass die geschriebene Reihenfolge dieser Bitfelder möglicherweise dem IEEE-Standard entspricht, der C ++ - Compiler sie jedoch möglicherweise neu anordnet oder neu ausrichtet. Dies ist jedoch nur eine kleine Fußnote, da es Epics Aufgabe ist, sich damit zu befassen. Sie sollten jede neue Compilerversion überwachen, um sicherzustellen, dass der Typ ordnungsgemäß funktioniert.
@JoshPetrie Punkt genommen, danke für die Klarstellung.
Dmitry Grigoryev
1
@JustinLardinois Aber FFloat32 enthält ein floatMitglied in der Gewerkschaft. Wenn floatalso tatsächlich mehr als 32 Bit vorhanden sind, ist dies auch insgesamt FFloat32der Fall, da die Gewerkschaft groß genug sein muss, um das größte Mitglied aufzunehmen. In Fällen, in denen Floats größer als vier Bytes sind, musste Epic auch die Bitfeldteile der Union ändern, um dies zu beheben. Andernfalls werden sie nicht den vollständigen Float abbilden.