I needed a custom float comparison for my project and I ended up using a method provided here: https://stackoverflow.com/a/3877206/393406
Though, knowing that float.GetHashCode() returns the bits as would the unsafe de-referencing variation of code, I skipped both the bit-conversion and de-referencing and am utilizing the GetHashCode() instead.
After finding out about the problem which I am experiencing, I tested if BitConverter would provide different values, but that's not the case.
The problem appears in two different places and coincidentally due to comparing the same values, respectively: 1f and -4f. The values made me curious and I went on to debug the case when the call to Math.Abs(a - b) hits the OverflowException (a - b being equal to Int32.MinValue).
I was quite surprised, when I found out, that the absolute hash codes (bit values) for 1f and -4f are the same, which ultimately, messes up the math.
I went on to debug a little more (also taking in mind some of the flaws provided here), providing different values (float -> GetHashCode()) and witnessing interesting results:
0f -> 0
-0f -> -2147483648
float.MinValue -> -8388609
float.MaxValue -> 2139095039
1f -> 1065353216
-1f -> -1082130432
2f -> 1073741824
-2f -> -1073741824
4f -> 1082130432
-4f -> -1065353216
The interesting parts being... given that 2f and -2f have the same, absolute, bit values:
- why there are differences for
1fand4fpairs? - why the
1fand4fpairs are somewhat inversely related?
I bet that my reasoning is totally illogical, but I'm just curious.
Well, and yes, the relation between 1f and -4f is killing my comparison, because:
int aBits = a.GetHashCode(); // -4 => -1065353216
if (aBits < 0)
aBits = Int32.MinValue - aBits; // -1082130432
int bBits = b.GetHashCode(); // 1 => 1065353216
if (bBits < 0)
bBits = Int32.MinValue - bBits; // no changes, 1065353216
int bitDifference = aBits - bBits; // -1082130432 - 1065353216 = -2147483648 = Int32.MinValue
int absoluteBitDifference = Math.Abs(bitDifference); // an obvious OverflowException
- How to prevent this problem?