Why float.CompareTo()
using big numbers don't work as expected?
Test numbers:
float a = 1000000000f;
float b = 1000000001f;
float c = 1000000002f;
float d = 999999999f;
Results:
a.CompareTo(a) = 0
a.CompareTo(b) = 0
a.CompareTo(c) = 0
a.CompareTo(d) = 0
The documentation says that:
- Less than zero: This instance precedes obj in the sort order.
- Zero: This instance occurs in the same position in the sort order as obj.
- Greater than zero: This instance follows obj in the sort order.
And as you can see the results says that a, b, c and d are the same.
But, if I use smaller numbers, like:
float a = 100000f;
float b = 100001f;
float c = 100002f;
float d = 99999f;
Results:
a.CompareTo(a) = 0
a.CompareTo(b) = -1
a.CompareTo(c) = -1
a.CompareTo(d) = 1
Comparing the numbers correctly.
I read Is floating point math broken? and I understand the precision errors when having decimal numbers. But why that big numbers without decimals have this unexpected results?
Context. Why using CompareTo?
I was working on some pathfinding algorithms like BFS, Dijkstra and A*, and I end up using IComparable in a class for my PriorityQueue, then while testing I got that errors. And while I solved all the errors in my algorithm, I want to know why that happened.
Edit
I test printing the value as @GSerg suggested, and I got more questions.
a.ToString("N0")
, b.ToString("N0")
, c.ToString("N0")
, d.ToString("N0")
, in the first scenario all four variables print: "1,000,000,000"
. And in the second scenario prints the correct smaller numbers.
Answer
As I understand, the reason of this behaviour is because a large float number is stored in a "scientific notation" like style, making them to lose precision with their decimals. And Is floating point math broken? explains that.