У Unreal, які відмінності між плавкою C ++ та FFloat32?


17

Я намагався вивчити деякі більш глибокі аспекти UE4, і читаючи багато прикладних кодів, а також вихідну базу двигуна, я помітив, що іноді люди (і сам вихідний код) використовують стандартний C ++ floatпримітив, але іноді використовують користувацьку реалізацію UE4 FFloat32.

Тоді мені стало цікаво: при програмуванні гри з Unreal які існують відмінності між тими двома варіантами і, можливо, які основні випадки, коли треба відмовитися від стандартного C ++ примітиву на користь реалізації двигуна?


1
Мені буде цікаво прочитати приклади, які ви насправді використовуєте FFloat32.

@JoshPetrie Деякі з них були офлайн, пара була в Інтернеті. Як тільки у мене з’явиться час вдома, я шукатиму їх, щоб поділитися
Кім Шуттер

Відповіді:


17

float, добре, плаваюча точка C ++. FFloat32являє собою структуру, яка представляє поплавок, а також (через об'єднання) розкладені бітові поля для знака, мантіси та експонентів цього поплавця.

Як правило, ніколи не використовуйте, FFloat32за винятком випадків, коли:

  • ви використовуєте деякі API, які очікують FFloat32(вони дуже рідкісні) або
  • вам потрібно зробити якийсь низький рівень біт-хакерів зі значенням плаваючої крапки (також досить рідко в ці дні)

Це не означає, що FFloat32це погано , по суті, це просто , що це на самому ділі не запропонувати вам все , що ви б необхідно для загального призначення з плаваючою точкою використання.

Він рідше, ніж звичайний старий float, який має незначний вплив на читабельність (інші можуть не відразу знати, для чого це потрібно). Він також не неявно перетворюється на floatтак, що ви будете набирати something.FloatValueбагато, що також не є великою справою, але може стати стомлюючим.

Нарешті, його використання об'єднань та бітполів не є портативним та визначено реалізацією (див. Нижче). Це не ваша проблема, завдання Epic - переконатися, що тип структурований таким чином, що він може бути використаний для всіх підтримуваних реалізацій, але це потенційне джерело помилок, якщо вони не зможуть знайти проблему з реалізацією типу при новому компіляторі версія випускається або додається до списку підтримуваних компіляторів.

Тому, якщо вам не потрібно грати з окремими бітами в поданні з плаваючою точкою, вам, мабуть, просто слід уникати FFloat32(його двоюрідний брат FFloat16, може мати трохи більше корисності, оскільки не існує стандартного 16-бітного типу C ++ з плаваючою точкою).

Раніше було маніпулювати поплавцями за допомогою цілих уявлень їх компонентів для " швидкості ". Сучасні комп’ютери позбавляють значної частини необхідності для багатьох платформ і різних методи штампування , які можна було б використовувати для подібних речей, насправді можуть завдавати шкоди для продуктивності чи коректності в будь-якому випадку.

Слід сказати, що пошук у сховищі GitHub Unreal виявляє дуже мало FFloat32типів використання. Усі вони є у визначенні FFloat32себе або у визначенніFFloat16 .


Зокрема, FFloat32робить дві речі, про які закликає стандарт C ++. Це:

  • дозволяє діяти так, ніби одночасно більше одного члена спілки; від вас очікується запис членам плаваючої точки і читання з одного з цілих членів (9.5.1, [class.union])
  • очікує, що розподіл бітового поля в союзі збігається з розподілом бітів значення плаваючої точки IEEE; однак, розподіл та вирівнювання членів бітфілдів у межах типу класу визначено реалізацією (9.6.1, [class.bit])

Unreal не пишеться в стандартному C ++, він написаний для конкретних компіляторів, для яких він написаний, тому поки вони роблять очікувану річ, стандарт не має значення.
користувач253751

Я б очікував, що ці бітфілди будуть досить портативними навіть у стандартних C / C ++, оскільки вони визначені стандартом IEEE, і будь-який компілятор, що використовує інший макет для float, отримав би не червону позначку, сумісну з IEEE 754 (і проблеми із сумісністю з великою кількістю наявного програмного забезпечення ).
Дмитро Григор’єв

3
Проблема (педантична) полягає в тому, що письмовий порядок цих бітових полів може відповідати стандарту IEEE, але компілятор C ++ може їх переупорядкувати або повторно вирівняти. Це лише незначна виноска, хоча робота з цим - Epic; вони повинні слідкувати за кожною новою версією компілятора, щоб перевірити, чи працює тип правильно.

@JoshPetrie Point взятий, дякую за роз’яснення.
Дмитро Григор’єв

1
@JustinLardinois Але FFloat32 містить floatчлена в союзі, тому якщо floatнасправді більше 32 біт, загальний результат FFloat32буде таким же, оскільки союз повинен бути достатньо великим, щоб утримувати найбільшого члена. У випадках, коли поплавці перевищують чотири байти, Epic доведеться змінювати частини біт-поля об'єднання, а також вирішувати це, інакше вони не будуть відображати повний плавець.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.