Is there a way to map floats to ints or unsigned ints so that with the exception of NaN, order is preserved?
So if a and b are floats, and F is the mapping function,
a < b implies F(a) < F(b) and a == b implies F(a) == F(b)
Yes. All N bit ints can be represented in a floating point representation that has at least N-1 mantissa bits (because of the implicit leading 1 bit that doesn't need to be stored) and an exponent that can store at least N, i.e. has log(N)+1 bits.
You can declare 8-, 16-, 32-, or 64-bit integer variables by using the __intN type specifier, where N is 8, 16, 32, or 64. The types __int8 , __int16 , and __int32 are synonyms for the ANSI types that have the same size, and are useful for writing portable code that behaves identically across multiple platforms.
A signed integer is a 32-bit datum that encodes an integer in the range [-2147483648 to 2147483647]. An unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0 to 4294967295]. The signed integer is represented in twos complement notation.
Single-precision floating-point format (sometimes called FP32 or float32) is a computer number format, usually occupying 32 bits in computer memory; it represents a wide dynamic range of numeric values by using a floating radix point.
Hm, just out of the DawsonCompare
routine in Game Programming Gems 6, it's a normal bit-cast followed by a sign flip (since negative floats order opposite then negative integers). I'll borrow that idea.
You have:
// 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; }
If you can guarantee your int
is 32 bits, you can just use that.
Fun fact: The book goes on to use this (note, not with the exact code I present, since I stripped out the float-to-int part) to compare floating point values with tolerance:
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; }
This compares floats as true if their integer representations are within a certain range. (He uses 1000 as a good default.) A branch-less version called the LomontCompare
is presented with the same idea, but you have to buy the book for that. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With