Perspectives on Floating Point(eigentales.com) |
Perspectives on Floating Point(eigentales.com) |
If you more mean the language level, and just having two different ways to represent floating point numbers in your code, it gets a little tricky to reason about because one of those may align with what the processor is doing natively and others won't, and so you'd have a software layer converting the behavior of the platform to what your language promises -- with very high overhead sometimes and almost no overhead other times. That kind of inconsistency isn't needed very often. It can become a real headache for testing and in the wild. It's easier for a language to just say "this is the way we do floats" and you adapt as needed.
So the more typical balance is to deal with that kind of thing at the library level. If you want numbers that behave a certain way, and it's not the way your language models them, you use a library that gives you the kind of numbers you want with the tangible awareness that they're likely "soft" and less efficient in some way.
These things come straight from overflow and underflow behaviour of floating point bit representations. I'd guess some sort of IEEE flag exists to emit an interrupt if over/underflow happens, but nobody really wants those.
I'm not an expert on architecture, but I would've guessed that the need to branch to process the error would be the wrench and that the use of NaN and the infinities allow better optimizations.
* What is +1/0? It has to be +Infinity -- nothing else will do.
* What is -1/0? It has to be -Infinity -- nothing else will do.
* What is 0/0? There's no way to tell from the information we've got -- it's undefined: Not A Number. (However, should 0/0 come up as a result of taking the quotient of two functions that happen to both reach zero at a point, then sometimes the limit of that quotient is meaningful, and might have a numerical result.)
IEEE-754 chose to signal these things in-band, so we get NaN and Infinity to deal with in our floats and doubles.
Many (most?) compilers already offer a “fast math” flag that foregoes denormals. You don’t need to remove denormals from the format in order to avoid them.
Having a separate type without specials would probably cause unending confusion and increase bugs. It’s already the case that only people who care about the specials handle them, but it sounds like there are more of those people than you think, if you think only mathematicians care about them.
It could easily be a compiler-based protection: any opcode that can generate it from two/one normal input must be checked for normal results.
This is similar to how C++ gives few guarantees but "new" and "this" never give null or unallocated values.
https://cnrs.hal.science/hal-04116310/document
And also Gerald Sussman saying:
> The only thing that scares me in programming is floating point.
You can, of course, do a very specialized optimization for one particular algorithm, but that tends to not be a very good use of time. Usually. (Counterexample: Kahan summation!)
Absolute error has useful applications, without any doubt, and regardless of arithmetic operation, but it probably doesn’t make sense to say it’s “better” without a specific problem in front of us, and without specific goals and priorities. Error tolerance is always up to the user.
Anyway, most CPUs support a trapping mode, after all. Here's an example with glibc:
#define _GNU_SOURCE
#include <fenv.h>
volatile double x = 1.0;
volatile double y;
volatile double quotient;
int
main(void)
{
feenableexcept(FE_DIVBYZERO);
quotient = x / y;
}
As far as I understand it, overall support for trapping math is poor because not much code is trapping-aware. It would be quite annoying if JSON parsing results in SIGFPE due to an Inexect trap, for example.