What is the ‘range’ of a number type?

In programming, we often represent numbers using types that have specific ranges. For example, 64-bit signed integer types can represent all integers between -9223372036854775808 and 9223372036854775807, inclusively. All integers inside this range are valid, all integers outside are “out of range”. It is simple.

What about floating-point numbers? The nuance with floating-point numbers is that they cannot represent all numbers within a continuous range. For example, the real number 1/3 cannot be represented using binary floating-point numbers. So the convention is that given a textual representation, say “1.1e100”, we seek the closest approximation.

Still, are there ranges of numbers that you should not represent using floating-point numbers? That is, are there numbers that you should reject?

It seems that there are two different interpretation:

  • My own interpretation is that floating-point types can represent all numbers from -infinity to infinity, inclusively. It means that ‘infinity’ or 1e9999 are indeed “in range”. For 64-bit IEEE floating-point numbers, this means that numbers smaller than 4.94e-324 but greater than 0 can be represented as 0, and that numbers greater than 1.8e308 should be infinity. To recap, all numbers are always in range.
  • For 64-bit numbers, another interpretation is that only numbers in the ranges 4.94e-324 to 1.8e308 and -1.8e308 to -4.94e-324, together with exactly 0, are valid. Numbers that are too small (less than 4.94e-324 but greater than 0) or numbers that are larger than 1.8e308 are “out of range”. Common implementations of the strtod function or of the C++ equivalent follow this convention.

This matters because the C++ specification for the from_chars functions state that

If the parsed value is not in the range representable by the type of value, value is unmodified and the member ec of the return value is equal to errc​::​result_­out_­of_­range.

I am not sure programmers have a common understanding of this specification.

Published by

Daniel Lemire

A computer science professor at the University of Quebec (TELUQ).

8 thoughts on “What is the ‘range’ of a number type?”

  1. float numbers/ real numbers is much complicated than integers. the range of float needs to worry about more than upper and lower bound, but also minimum closet difference between any two consecutive float number.

  2. I find it weird that 0.0 1 is out of range (not rounded to 0), but 1.0 1 is not out of range, and rounded instead to 1. The round-trip behavior might also be weird for numbers very close to (but not exactly) 0.

    gcc 11.2 can parse 2.22507e-308, but a bit below that is out of range.

      1. I find it weird that 0.0 (…400 times 0…) 1 is out of range (not rounded to 0), but 1.0 (…400 times 0…) 1 is not out of range, and rounded instead to 1.

        The round-trip behavior might also be weird for numbers very close to (but not exactly) 0: I’m wondering if it will always work as expected if a number is first converted to a string, and then parsed again.

        gcc 11.2 can parse 2.22507e-308, but a bit below that is out of range. This doesn’t match the bound you gave with of 4.94e-324.

  3. It’s probably best to consider 64-bit floating point range to be from 1.1e-308 to 1.8e308, i.e. excluding denormal values. Including denormal numbers is problematic because of the loss of precision. Including numbers beyond that is pointless because they are not representable.

Leave a Reply

Your email address will not be published.

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

You may subscribe to this blog by email.