Есть ли способ сопоставить float с ints или unsigned ints, чтобы, за исключением NaN, порядок сохранялся?
Итак, если a и b - float, а F - функция отображения,
a < b означает F (a) Р (б) а также a == b означает F (a) == F (b)
Есть ли способ сопоставить float с ints или unsigned ints, чтобы, за исключением NaN, порядок сохранялся?
Итак, если a и b - float, а F - функция отображения,
a < b означает F (a) Р (б) а также a == b означает F (a) == F (b)
Hm, только из подпрограммы DawsonCompare
в Game Programming Gems 6, это нормальный бит-литой, за которым следует знак с переворотом (так как отрицательный порядок float противоположно отрицательным целым числам). Я займусь этой идеей.
У вас есть:
// utility
template <typename R, typename T>
R& bit_cast(T& pX)
{
return reinterpret_cast<R&>(pX);
}
// int32_t defined in <boost/cstdint.hpp>.
boost::int32_t float_to_int_bits(float pX)
{
boost::int32_t x = bit_cast<boost::int32_t>(pX);
if (x < 0)
x = 0x80000000 - x;
return x;
}
Если вы можете гарантировать, что ваш int
равен 32 бит, вы можете просто использовать это.
Интересный факт: в книге используется это (обратите внимание, что не с точным кодом, который я представляю, так как я удалил часть float-to-int) для сравнения значений с плавающей запятой с допуском:
bool DawsonCompare(float pX, float pY, int pDiff)
{
int x = float_to_int_bits(pX);
int y = float_to_int_bits(pY);
int diff = x - y;
return abs(diff) < pDiff;
}
Это сравнивает float как true, если их целочисленные представления находятся в определенном диапазоне. (Он использует 1000 как хороший дефолт.) Версия без ветки, называемая LomontCompare
, представлена с той же идеей, но для этого вам нужно купить книгу.:)
Только для устранения потенциально медленного if
из других ответов...
int32_t float_to_int( float f ) {
int32_t i = reinterpret_cast< int32_t& >( f );
uint32_t sgn = static_cast< uint32_t >( i ) >> 31;
return i ^ -sgn & numeric_limits<int32_t>::max();
}
Обратите внимание, что в отличие от другого решения это неправильно обрабатывает 0
и -0
. Как float они сравнивают равные, но после сопоставления с целыми числами они становятся 0
и -1
соответственно. Как единая икота в числовой строке, я не думаю, что было бы легко обрабатывать этот случай без инструкции перехода.
Конечно, это предполагает две арифметические дополнения, float
- IEEE 754 с одной и той же конечностью и одно и то же адресное пространство для float и int и т.д.