Подтвердить что ты не робот

Сопоставьте 32-битный float с 32-битным целым числом

Есть ли способ сопоставить float с ints или unsigned ints, чтобы, за исключением NaN, порядок сохранялся?

Итак, если a и b - float, а F - функция отображения,

a < b означает F (a) Р (б) а также a == b означает F (a) == F (b)

4b9b3361

Ответ 1

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, представлена ​​с той же идеей, но для этого вам нужно купить книгу.:)

Ответ 2

Только для устранения потенциально медленного 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 и т.д.