First, a point I didn't make, is that if you have 32 bits of fixed, you get way more precision than with a 32 bit float.
That's true, but I already responded to it. If you step up to the next size of float (e.g. f64), you have more precision than the fixed32. You can do exactly the same computation in f64 with equivalent inputs, and you'll get better precision than doing it in fixed32. Or you can round at every step like fixed does and get a bit-equivalent value if you don't want the precision. It's less memory efficient, but my point is that the remaining use cases for fixed point are exceptional/situational and getting increasingly niche.Maybe using a bigger float type is cheating, but it's basically free because of the ubiquitous support for floats.
In contrast, with floats, you can lose precision.
This only happens with values outside the range of your fixed point type if you use larger floats as mentioned above. I consider that a different argument. You can alternatively view this as the float handling a situation more gracefully than fixed point would have. Afaik finance people don't even use floats for things like account balances, because you can't represent something like 0.1$ exactly.
Finance types typically use decimal types from what I understand. This is really just the result of using a decimal syntax to initialize/output a binary representation. Fixed point has exactly the same problem. Decimals have an analogous issue with the value 1/3. It has other advantages, like your calculation running the exact same regardless of CPU and/or compiler, which I'm sure a lot of analysts care about.
I wrote a library that makes floats more practically deterministic across platforms for very little cost (linked at [0] so you can see the limitations and numbers), and the underlying problem is [maybe] getting a standardized solution in C++29. You can get the same thing today just by changing compiler flags. If you need the special, non-reproducible float functions, your options are mainly to import a library or implement it yourself, same as fixed point. Not trying to be antagonistic, just figure out where you're coming form.
I work in safety-critical automotive/robotics, used to do audio DSP, contributed a bit to the aforementioned standardization, etc. I also have a talk on this topic I've been working on for the last few weeks. It's a bit of a pet subject. Fixed point has basically no language support, and is very hard to get right, but sometimes you need to do that.
There are absolutely situations for it, but that's exactly it: it's situational. And those situations are increasingly uncommon these days, now that hardware with good IEEE support is essentially ubiquitous and compilers/standard libraries are improving their implementations.
Thanks for answering my points in detail! I think this is one of those domains where there's enough theory and practical considerations, that basically given the same set of constraints, there's generally one set of correct conclusions.
To be clear I'm not anti-float, as they have less surprising behavior than fixed point, and are much less fiddly, but I do have to note that f32 sits at that awkward spot where it's not accurate enough for a lot of numerical work, but stepping up to f64 carries a significant performance penalty on things like GPUs, and most DSPs don't really give you f64 hardware at full rate, if at all.
In contrast, 32 bit fixed point gives you 6 extra bits of precision, (IEEE754 mantissa should count as 26 bit), which can often be the saving grace.
For example, in video games, if you mandate a 0.01mm precision, with int32, you get a 40kmX40km area, which is plenty, and with float32, you have to divide every dimension by 64, which is not enough for even mid-sized maps, and you have to employ tricks or go straight to f64.