I will say, generally, it depends on what you mean. There's like, numerical drift, and then there's converting to the discrete part. Generally, I'd say that "getting into the discrete part" of an algorithm, unless you're trying to match behavior of another piece of software, is fine. Like, if you're playing a game, people are not going to care if the shot just grazed them and missed, but the "Actual True Value" is like 10^-9 off or something. They will just chalk it up to "close, unlucky". If you have one canonical place for your floating point errors from which your "discrete" parts derive, it's no biggie.
But at work, I recently debugged an algorithm in which the author, effectively wanted to compute the integer and fractional parts of a double type. Their reasoning was that, for the fractional part, there can be imprecision, so you should do some fancy math to recover the fractional part.
This is giga wrong for the application we were building. You never want to try computing the "same double" in two different ways and compose the results like this. Intuitively, if one path "thinks" your double is 15.00001, and the other path "thinks" its 14.99999, you're now saying that the double is 15 (integer) + .99999 (fractional) = 15.99999: this is way off now!
You should just use one double, and extract out the integer and fractional parts. It doesn't matter if the double is imprecise - it's authoritatively imprecise. Much easier to reason about.
This is the first time I've debugged an edge case like this since I wouldn't implement something like this, but it's an example of how subtle floating point errors can be.
i5 and i7 are terms which lack precision. Are you seeing different results for the same operations on the same arguments in the same order across an i5 and an i7 with the same core architecture?
Regardless, it would be great if you have examples of operations that have different results on different processors; my expectation was that I could expect same width, same operation, same arguments to provide the same result across most x86 processors (early pentiums not dividing properly and maybe more variance in the socket 7 days where there were so many vendors). Most of the issues I've seen documented were not running the same sequence of operations especially around 80-bit floats on x87 if something spills to a 64-bit double in memory. All that said, I prefer to deal in integers whenever possible, I know the edges of floating point are sharp, and I'd rather not be cut.
It's probably the determinism and reproducibility that's the key constraint in HFT settings. In other industries it's just generic textbook numerical analysis (analyze batched eps error), and then in engineering land it's "ehh good enough".
On multiple occasions I’ve seen noticeable accumulated rounding error crop up by the end of a cumprod over very long timeseries of floats.
But in my cases it has just been a minor nuisance that I have to double check whether a mismatch came from float-related quirkiness or a code mistake.
I got into the habit of just using integers where applicable for cases that need to match down to the last bit, and numpy.isclose() for inherently floaty cases where it’s anticipated and reasonable.
Only speaking from my own experience, which doesn’t involve chaotic systems or anything like that. I’m curious to hear from people in other domains who may have more exciting stories.