Hacker News new | ask | show | jobs
by pclmulqdq 847 days ago
IEEE 754 has an infinity, so division by zero isn't the catastrophic thing that it is in integer. However, division by zero is still an exception as defined by the 754 standard.

What hardware does with these exceptions is a separate question, though. Some CPUs will swallow them for performance.

2 comments

there's a whole set of terminology about 'exceptions', 'traps', and 'signaling' in ieee 754 that i don't really understand, but in particular the second thread i linked there seems to claim that an ieee 754 'exception' is almost, but not quite, completely unlike a python 'exception', which it apparently calls a 'trap' (as do many cpu architectures):

> When exceptional situations need attention, they can be examined immediately via traps or at a convenient time via status flags. Traps can be used to stop a program, but unrecoverable situations are extremely rare.

you know quite a bit about cpus. do you know of any ieee-754 cpus that trap on floating-point division by zero by default? is there a way to configure commonly-used cpus to do so?

I have been involved in the IEEE 754 committee on and off, so I will say that exceptions in the current standard are purposely sort of ambiguous in order to allow parallel and hardware implementations to also be standards-compliant (rather than just serial CPUs), and the exception-handling discussion has already been raised again for 754-2029. Exceptions as defined in the standard are the general form of error handling for IEEE 754.

Signaling NaNs (sNaN) are the only form of "signaling" that I am aware of, and sNaNs are just set up to trigger an "invalid operation" exception. I believe the idea is that an operation raises an sNaN when it creates a NaN, and a subsequent operation can catch it and issue the exception so you can figure out exactly where the calculation went wrong. If you ignore that exception, the sNaN becomes a quiet NaN (qNaN) and propagates.

The idea of traps have been written out of the standard in favor of exceptions. Traps had a defined behavior, which is what you would expect as an "exception" in most programming languages. A sibling comment indicated how to enable the FP exceptions as CPU interrupts, which become OS traps, and then become exceptions in Python/Java/C++ (any language with exceptions). Totally not confusing terminology at all.

I don't know off the top of my head of any architecture that treats all the exceptions in this way by default. One of the other exceptions is "inexact" which comes up on many calculations. I don't think you would want that to generally cause a CPU interrupt. Most implementations dump the exceptions as flags into a status register and let you see what happened if you care.

thank you, this helps a lot!
On Linux, fpenableexcept(3) lets you do this.
aha! feenableexcept! i'd never heard of it!

    // Demonstrate C99/glibc 2.2+ feenableexcept

    #define _GNU_SOURCE
    #include <math.h>
    #include <fenv.h>
    #include <stdlib.h>
    #include <stdio.h>

    int main(int argc, char **argv)
    {
      if (argc != 3) {
        fprintf(stderr, "Usage: %s a b  # floating-point divide a by b\n", argv[0]);
        return 1;
      }

      feenableexcept(FE_DIVBYZERO);
      double a = atof(argv[1]), b = atof(argv[2]);
      printf("%g รท %g = %g\n", a, b, a/b);
      return 0;
    }
is the machine still ieee-754-compliant after you call feenableexcept? i'm guessing that if it weren't, intel wouldn't have defined the architecture to have this capability, given the historically close relationship between 8087 and ieee-754
See my other comment, but it's still compliant. You are allowed to handle exceptions in a lot of different ways.
IEEE 754 has infinity, it has signed zeros, but it doesn't have the absolute zero. For the math to be entirely correct it is not enough. I wonder why it was done like this.
+/-0 should generally be thought of as 0. It's just "0 from the right" and "0 from the left." The reason it has +/-0 is for a few specific applications:

- Some people really do want 1/(-x) to be negative infinity when a positive x reaches underflow. This helps with some kinds of numerical simulations since it can preserve the sign bit through underflow.

- Interval arithmetic implementations need to be able to disambiguate closed and open intervals at 0.

If you turn on fast math mode, you can also essentially disable the special treatment of the zeros.

But still, why there is no absolute 0 - the third zero? I would prefer something like this:

  1 / +0 == +inf
  1 / -0 == -inf
  1 / 0 == nan
  abs(-0) == 0
But it is not possible as there is no unsigned/absolute zero: 0 means +0. I guess it makes things much simpler, but IMHO it makes it a bit less useful and strange.
I think if you treat infinity as a special case of NaN (which it basically is for many math systems), you get the behavior you want. A lot of people think that +/-0 represent +/-epsilon, but they really don't. +0 is the default 0, and -0 is what you get when you underflow specifically from the left.
you're in luck! that's such a frequently asked question that kahan has written several papers about it, and there's a wikipedia page too: https://en.wikipedia.org/wiki/Signed_zero