Say I want a function that takes two floats (x
and y
), and I want to compare them using not their float
representation but rather their bitwise representation as a 32-bit unsigned int
. That is, a number like -495.5
has bit representation 0b11000011111001011100000000000000
or 0xC3E5C000
as a float
, and I have an unsigned int
with the same bit representation (corresponding to a decimal value 3286614016
, which I don't care about). Is there any easy way for me to perform an operation like <=
on these floats using only the information contained in their respective unsigned int
counterparts?
To compare two floating point values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.
Single-precision values with float type have 4 bytes, consisting of a sign bit, an 8-bit excess-127 binary exponent, and a 23-bit mantissa. The mantissa represents a number between 1.0 and 2.0.
There are 4 (5) different ways to compare floating-point numbers. They are: Bitwise comparison. Direct ("exact") IEEE-754 comparison.
How To Compare Floats in Python. If abs(a - b) is smaller than some percentage of the larger of a or b , then a is considered sufficiently close to b to be "equal" to b . This percentage is called the relative tolerance. You can specify the relative tolerance with the rel_tol keyword argument of math.
You must do a signed compare unless you ensure that all the original values were positive. You must use an integer type that is the same size as the original floating point type. Each chip may have a different internal format, so comparing values from different chips as integers is most likely to give misleading results.
Most float formats look something like this: sxxxmmmm
s
is a sign bitxxx
is an exponentmmmm
is the mantissa
The value represented will then be something like: 1mmm << (xxx-k)
1mmm
because there is an implied leading 1
bit unless the value is zero.
If xxx < k
then it will be a right shift. k
is near but not equal to half the largest value that could be expressed by xxx
. It is adjusted for the size of the mantissa.
All to say that, disregarding NaN
, comparing floating point values as signed integers of the same size will yield meaningful results. They are designed that way so that floating point comparisons are no more costly than integer comparisons. There are compiler optimizations to turn off NaN
checks so that the comparisons are straight integer comparisons if the floating point format of the chip supports it.
As an integer, NaN
is greater than infinity is greater than finite values. If you try an unsigned compare, all the negative values will be larger than the positive values, just like signed integers cast to unsigned.
If you truly truly don't care about what the conversion yields, it isn't too hard. But the results are extremely non-portable, and you almost certainly won't get an ordering that at all resembles what you'd get by comparing the floats directly.
typedef unsigned int TypeWithSameSizeAsFloat; //Fix this for your platform
bool compare1(float one, float two)
union Convert {
float f;
TypeWithSameSizeAsFloat i;
}
Convert lhs, rhs;
lhs.f = one;
rhs.f = two;
return lhs.i < rhs.i;
}
bool compare2(float one, float two) {
return reinterpret_cast<TypeWithSameSizeAsFloat&>(one)
< reinterpret_cast<TypeWithSameSizeAsFloat&>(two);
}
Just understand the caveats, and chose your second type carefully. Its a near worthless excersize at any rate.
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