← Back to context

Comment by amelius

2 days ago

I'm curious why we have not-a-number, but not not-a-string, not-a-boolean, not-an-enum, and not-a-mycustomtype.

Because NaNs come from a standardized hardware-supported type, whereas the rest of those are largely language-specific (and you could consider null/nil as a "not-a-*" type for those in applicable languages; and there are languages which disallow NaN floats too, which completes all combinations).

Itanium had a bit for "not a thing" for integers (and perhaps some older hardware from around the time floats started being a thing had similar things), so the idea of hardware support for not-a-* isn't exclusive to floats, but evidently this hasn't caught on; generally it's messy because it needs a bit pattern to yoink, but many types already use all possible ones (whereas floats already needed to chop out some for infinities).

Because IEEE 754 creators wanted to signal non-trapping error conditions for mathematically undefined operations, and they had a plenty of bit patterns to spare. Apparently back in the 70s and 80s in many cases it was preferable for a computation to go through and produce NaNs rather than trapping instantly when executing an undefined operation. I'm not quite sure what the reasoning was exactly.

  • In early FP machines the floating point processor could not take a trap at a faulting instruction precisely: it could only go bad things. Furthermore for programmers and hardware it can be very expensive. Rather than go through a loop and filter NaN out of results it becomes trap every time and resume and is a pain.

Some common numeric operations can result in non-numbers(eg division by zero - Nan or infinity).

Are there any common string operations with similar behavior?

  • Out of range substring? Some languages throw an error, others return an empty string. You could return a propagating NaS instead. I don't know what you'd use it for.

Nana basically means that floating point arithmetic is predicting that your mathematical expression is an "indeterminate form", as in the thing you learn in calculus.

Because representing infinity is not possible outside of symbolic logic and isn’t encodable in floats. I think it is a simple numerical reason and not a deeper computer reason.

  • Well, infinity is totally representable with IEEE 754 floats. For example 1.0/0.0 == +inf, -1.0/0.0 == -inf, but 0.0/0.0 == NaN.

    • A smart compiler should be able to figure out a better value for 0/0, depending on context.

      For example:

          for i in range(0, 10):
              print(i/0.0)
      

      In this case it should probably print +inf when i == 0.

      But:

          for i in range(-10, 10):
              print(i/0.0)
      

      Now it is not clear, but at least we know it's an infinity so perhaps we need a special value +-inf.

      And:

          for i in range(-10, 10):
              print(i/i)
      

      In this case, the value for 0/0 can be 1.

      1 reply →