today I'm thinking about the "don't use floating point for money" advice I hear all the time. It obviously has a lot of truth to it.

But -- Excel/Google Sheets uses floating point for all of its calculations, people use spreadsheets for money calculations all the time, and it generally seems to work just fine -- the results get rounded for display.

So I'm trying to figure out if there's a more nuanced guideline than "never use floating point for money".

thinking about trying to define a "safe zone" and a "danger zone" for floating point. maybe something like:

safe zone:
* all integer values (like 1.0, 234.0) behave 100% exactly the way you'd expect, UNLESS (!!!) they're more than 2^52. You can check for equality, it's fine.
* adding up ~100 numbers and rounding the result to 4 decimal places or so is going to work fine, as long as the numbers are roughly the same size

@b0rk One thing about floating point that I find fascinating is issues that arise when using them for coordinates in things like video game worlds.

The "really weird" thing about floats is how they loose decimal precision as the whole number part gets larger.

So, when using floats for game coordinates, you have to be careful about "how far from the origin am I" because the farther you go, the lower precision, and thus, the lower fidelity you'll have on positions: Even for polygon vertices!

@b0rk Also, it's important to be really precise when you say "floating point" do you mean 32-bit floats or 64-bit double precision (doubles). There's a huge difference in the decimal precision!

For example, "float for latitudes & longitudes" is well known to cause lots of precision-related issues. 32-bit floats are generally "not precise enough" for these kinds of coordinates. You have to *always* use doubles.

@b0rk Another thing that really blows my mind about floats is issues when thinking about them as line vertices.

For example, if you have two lines, one from (0,0) to (1,1) and another from (0,1) to (0.5,0) and you compute "the intersection point between these two lines" you have to remember that the intersection point doesn't actually lie on either line! It will be some position just slightly off due to precision issues.

@b0rk This gets even tricker and non-intuitive dealing with polygons.

For example, when computing the intersection between two polygons, its actually possible for the area of the intersection to be larger than the area of one or both of the input polygons!

This generally will only happen when the input polygons are "quite close to" the precision limit of the float (i.e. 1E-7 or thereabouts for 32-bit).

But, "really long and skinny" polygons can result in other similarly bizarre cases.

@b0rk One last bizarreness:

std::numeric_limits<float> returns some ... surprisingly un-intuitive values!

For example,

std::numeric_limits<int32_t>::min() is "-2^31" (i.e. a large negative number)

BUT

std::numeric_limits<float>::min() gives the unexpected value 1.17549e-38 which is actually "the smallest positive value"

If you want "the smallest value that can be represented" you should use ::lowest() instead.