Why are floats so cursed? I ask that non-rhetorically. It's not only ye olde NaN!=NaN; like half of the virtual ink spilled on nailing down language semantics also ends up being about arcane float-related esoterica. Is this, e.g., somehow inherent to the problem space? A weird historical clusterfuck? Something else? (Most recently reminded by: https://github.com/rust-lang/unsafe-code-guidelines/issues/471)
@glaebhoerl my theory: floats are cursed because people want real numbers, but real numbers are tricky because actual constructible real numbers have a lot of undesirable properties, like the inability to determine digits. real numbers are a connected type, so the only functions from R to Bool that respect continuity are constant functions. so either we have analog computers, or we must work with approximations. and that leads to shenanigans.
@typeswitch The need to be approximate is indeed *part* of the cursedness (implying non-associativity too) and the part that seems most inescapable. But so much else seems unforced. NaN bit patterns, global mutable fenv, denormals, x87, NaN!=NaN of course, -0 == +0, and there's more I'm probably forgetting. Everything designed by humans has flaws, but why such a concentration.
looking into it, it seems that the design of FP follows mostly from the need for operations to be closed.
NaN is good, actually -- it says "you did something wrong" rather than just giving you a wrong value.
global mutable fenv (& x87 state) is just an ABI issue tho? it's global state, so it's like everything else in these cursed machines -- e.g. registers are global state -- and the point of ABIs is for people to manage all that global state in a compatible way.
@typeswitch I think the idea is -- since it's all approximate anyways -- to conflate zero with infinitesimal. Which makes some sense, in the same kind of way that NaN!=NaN makes sense because conceptually NaNs are not any particular known value. But violating reflexivity and congruence of equality are both bad.