W Unreal, jakie są różnice między float C ++ a FFloat32?

17

Próbowałem nauczyć się głębszych aspektów UE4 i podczas czytania wielu przykładów kodów, a także bazy źródłowej silnika, zauważyłem, że czasami ludzie (i sam kod źródłowy) używają standardowego floatprymitywu C ++ , ale czasami używają niestandardowej implementacji UE4 FFloat32.

Potem się zaciekawiłem: kiedy programuję grę w Unreal, jakie są różnice między używaniem tych 2 opcji i być może w jakich głównych przypadkach należy porzucić standardowy prymityw C ++ na rzecz implementacji silnika?

Kim Shutter
źródło
1
Byłbym zainteresowany przeczytaniem przykładów, które faktycznie wykorzystałeś FFloat32.
@JoshPetrie Niektóre z nich były offline, kilka było online. Jak tylko będę miał czas w domu, szukam ich do podzielenia się
Kim Shutter

Odpowiedzi:

17

float, jest dobrze zmiennoprzecinkowe w C ++. FFloat32jest strukturą, która reprezentuje liczbę zmiennoprzecinkową, a także (za pośrednictwem unii) zdekomponowane pola bitowe dla znaku tego elementu, części mantysy i wykładnika.

Zasadniczo nigdy nie należy używać, FFloat32z wyjątkiem sytuacji, gdy:

  • używasz interfejsu API, który oczekuje FFloat32(są one bardzo rzadkie) lub
  • musisz zrobić coś w rodzaju hakowania bitów na niskim poziomie z wartością zmiennoprzecinkową (obecnie również dość rzadkim)

Nie FFloat32jest źle , po prostu, po prostu nie oferuje niczego, czego potrzebujesz do ogólnego zastosowania zmiennoprzecinkowego.

Jest mniej powszechny niż zwykły stary float, który ma niewielki wpływ na czytelność (inni mogą od razu nie wiedzieć, do czego służy). Nie jest też domyślnie konwertowany na, floatwięc będziesz something.FloatValuedużo pisać , co również nie jest wielką sprawą, ale może być nudne.

Wreszcie, użycie związków i pól bitowych jest nieprzenośne i zdefiniowane w implementacji (patrz poniżej). To nie jest twój problem, zadaniem Epica jest upewnienie się, że typ jest tak skonstruowany, aby można go było używać we wszystkich obsługiwanych implementacjach, ale jest to potencjalne źródło błędów, jeśli nie wychwycą problemu z implementacją typu, gdy nowy kompilator wersja została wydana lub dodana do listy obsługiwanych kompilatorów.

Tak więc, chyba że musisz grać pojedynczymi bitami w reprezentacji zmiennoprzecinkowej, powinieneś prawdopodobnie po prostu unikać FFloat32(jej kuzyn FFloat16, może mieć nieco większą użyteczność, ponieważ nie ma standardowego 16-bitowego typu zmiennoprzecinkowego C ++).

Kiedyś było tak powszechne manipulować pływaków pośrednictwem przedstawicielstw całkowite ich komponentów dla „ prędkość ”. Współczesne komputery eliminują wiele z potrzeby posiadania wielu platform, a różne techniki znakowania czcionkami , które mogą być użyte do tego rodzaju czynności, mogą w rzeczywistości w każdym przypadku być szkodliwe dla wydajności lub poprawności.

Warto powiedzieć, że wyszukiwanie w repozytorium GitHub Unreal ujawnia bardzo niewiele zastosowań tego FFloat32typu. Wszystkie są w definicji FFloat32siebie lub w definicji FFloat16.


W szczególności FFloat32robi dwie rzeczy, które wywołuje standard C ++. To:

  • pozwala działać tak, jakby więcej niż jeden członek związku działał jednocześnie; musisz pisać do elementów zmiennoprzecinkowych i czytać z jednego z elementów całkowitych (9.5.1, [class.union])
  • oczekuje, że przydział pola bitowego w unii będzie zgodny z przydziałem bitowym wartości zmiennoprzecinkowej IEEE; jednak przydział i wyrównanie elementów pola bitowego w ramach typu klasy jest zdefiniowane w implementacji (9.6.1, [class.bit])

źródło
Unreal nie jest napisany w standardowym C ++, jest napisany dla konkretnych kompilatorów, dla których jest napisany, więc dopóki robią to, czego oczekują, standard nie ma znaczenia.
user253751,
Oczekiwałbym, że te pola bitowe będą dość przenośne nawet w standardowym C / C ++, ponieważ są one zdefiniowane przez standard IEEE, a każdy kompilator używający innego układu floatnie uzyskałby czerwonego znaku zgodnego z IEEE 754 (i problemy z kompatybilnością z wieloma istniejącymi programami ).
Dmitrij Grigoriew
3
Problem (pedantyczny) polega na tym, że kolejność zapisu tych pól bitowych może być zgodna ze standardem IEEE, ale kompilator C ++ może zmienić ich kolejność lub ponownie je wyrównać. To tylko niewielki przypis, ponieważ zajmowanie się tym jest zadaniem Epica; powinni monitorować każdą nową wersję kompilatora, aby sprawdzić, czy typ działa poprawnie.
@JoshPetrie Point podjęte, dzięki za wyjaśnienia.
Dmitrij Grigoryev,
1
@JustinLardinois Ale FFloat32 zawiera floatczłonka w związku, więc jeśli w floatrzeczywistości jest większy niż 32 bity, ogólnyFFloat32 będzie, ponieważ związek musi być wystarczająco duży, aby pomieścić największego członka. W przypadkach, gdy zmiennoprzecinkowe są większe niż cztery bajty, Epic będzie musiał zmodyfikować części pola bitowego unii, aby rozwiązać ten problem, w przeciwnym razie nie zmapują pełnego zmiennoprzecinkowego.