Я рассматривал возможность публикации этого вопроса на GameDev, так как мой случай связан с игровым проектом, но я решил, что это больше подходит для более широкого программирования SE. . Пожалуйста, дайте мне знать, если этот вопрос будет лучше размещен там в конце концов.
Насколько я понимаю — и, пожалуйста, поправьте меня, если я ошибаюсь — разработка игр для мобильных устройств (в моем случае) может значительно выиграть от использования вычислений с фиксированной точкой, поскольку это обеспечит большую согласованность между платформами и повысит производительность. случаях, когда устройство не приспособлено для правильной обработки операций с плавающей запятой.
Но у фиксированной точки есть ограничения, особенно связанные с переполнением. Итак, мой вопрос: если мы определили, что фиксированная точка является лучшей альтернативой для целевых платформ, как определить, позволяют ли требования данного проекта их использовать.
Чтобы было понятнее, я хотел бы поделиться небольшим количеством кода, с которым у меня возникли проблемы:
CIwVec2 calculateBezier(float t, CIwVec2 p0, CIwVec2 p1, CIwVec2 p2) {
float u = 1 - t;
CIwVec2 p = IW_FIXED(u * u) * p0; // (1 - t)²P0
p += IW_FIXED(2 * u * t) * p1; // 2(1 - t)tP1
p += IW_FIXED(t * t) * p2; // t²P2
return p;
}
В этом проекте я использую Marmalade SDK, который использует C++ и поставляется с собственной реализацией чисел с фиксированной точкой (у них есть как 16-, так и 32-разрядные, я использую 32-разрядные на данный момент) и класс Vector (CIwVec2), который использует эту реализацию для позиционирования и вычислений (включая скалярное умножение, которое показано в коде выше). О, и IW_FIXED — это просто макрос для преобразования чисел с плавающей запятой в числа с фиксированной точкой.
Когда я пытаюсь запустить приведенный выше код, я получаю сообщение об ошибке Multiply overflow. Отладьте значения следующим образом:
t = 0
u = 1 (which converts to 4096 in int32 fixed-point with IW_FIXED)
p0.x = 1638400 (400.0f with IW_FIXED_TO_FLOAT)
p0.y = 409600 (100.0f with IW_FIXED_TO_FLOAT)
Честно говоря, у меня нет полного представления о числах с фиксированной точкой. Я понимаю эту идею, но операции с фиксированной точкой мне не совсем понятны (должно быть, я пропустил большинство математических занятий, связанных с основанием 2, позор мне). Но меня совершенно сбивает с толку тот факт, что что-то такое простое, как 1.0f * 400.0f, может вызвать переполнение в фиксированной точке.
Итак, хотя я думал, что у меня не будет проблем с поддержкой фиксированной точки в моем проекте, похоже, что это может быть не так. Игра представляет собой автомобильную игру с видом сверху, в которой не будет огромных трасс или чего-то еще, но они должны быть как минимум такими же большими, как экран устройства (или, что еще лучше, его разрешение), и, поскольку мы стремимся для планшетов также проблемы с чем-то вроде 1.0f * 400.0f означают, что о фиксированной точке не может быть и речи.
Я прав с этим предположением? И для будущих проектов и для других людей с похожими проблемами, как мы можем оценить жизнеспособность чисел с фиксированной точкой в проекте? Кроме того, как выбрать между 16-битным и 32-битным было бы отличным бонусом :)
(Извините за длинный пост и спасибо за ваше время!)
Обновление:
Итак, подытожим немного ответов на данный момент. Идеальным сценарием было бы реализовать ваши числа с фиксированной точкой таким образом, чтобы иметь необходимый диапазон для ваших нужд (ответ Mooing Duck). Кроме того, для операций с 32-битными числами безопаснее всего рассчитывать с использованием 64-битных (ответ timday и комментарий Макса). Кстати, в Marmalade есть некоторые функции «безопасного фиксированного умножения», но это не относится к перегрузке оператора скалярного умножения для CIwVec2 (который использует IW_FIXED_MUL
внизу, что не обеспечивает безопасного умножения).
И, наконец, что касается моего конкретного сценария, похоже, что начиная с Marmalade 6.1 простое использование поплавков, вероятно, было бы лучшим решением.
Редактировать: хотя ответ Макса действительно решил мою проблему, в основном потому, что это было что-то конкретное для Marmalade. Из-за этого я выбрал ответ Mooing Duck в качестве выбранного ответа, так как я чувствую, что он поможет большему количеству людей в целом.