Я работаю на платформе, которая имеет ужасные ларьки при сравнении поплавков с нулем. В качестве оптимизации я увидел следующий код:
inline bool GreaterThanZero( float value )
{
const int value_as_int = *(int*)&value;
return ( value_as_int > 0 );
}
Глядя на сгенерированную сборку, киоски исчезли, и функция стала более производительной.
Это работает? Я в замешательстве, потому что все оптимизации для трюков IEEE используют SIGNMASKS и множество операций AND / OR (http://www.lomont.org/Math/Papers/2005/CompareFloat.pdf например). Помогает ли приведение к подписанному int? Тестирование в простой проводке не обнаруживает проблем.
Любое понимание было бы хорошо.
Выражение *(int*)&value > 0
тесты если value
является любым положительным числом с плавающей точкой от наименьшего положительного денормаля (который имеет то же представление 0x00000001
) до наибольшего конечного числа с представлением 0x7f7fffff
) а также +inf
(который имеет такое же представление, как 0x7f800000
). Хитрость обнаруживает как положительное количество, но не все, представления NaN (представления NaN выше 0x7f800001
). Хорошо, если вам не нужны некоторые значения NaN, делающие тест верным.
Это все работает из-за представление форматов IEEE 754.
Функции манипуляции с битами, которые вы видели в литературе для целей эмуляции операций IEEE 754, вероятно, были нацелены на идеальную эмуляцию с учетом особенностей поведения NaN
и подписанные нули. Например, вариация *(int*)&value >= 0
не будет эквивалентно value >= 0.0f
, так как -0.0f
в виде 0x80000000
как без знака Int и, таким образом, как -0x80000000
как подписанный, делает последнее условие истинным, а первое ложным. Это может сделать такие функции довольно сложными.
Делает ли бросок подписанный
int
Помогите?
Ну да, потому что знак биты float
а также int
находятся в том же месте, и оба указывают положительное число, когда не установлено. Но состояние value > 0.0f
может быть реализовано путем повторного перевода value
как целое число без знака тоже.
Примечание: преобразование в int*
адреса value
нарушает строгие правила псевдонимов, но это может быть приемлемо, если ваш компилятор гарантирует, что он придает смысл этим программам (возможно, с параметром командной строки).