Arlen
Arlen

Reputation: 6835

How many distinct floating-point numbers in a specific range?

How many rep­re­sentable floats are there be­tween 0.0 and 0.5? And how many representable floats are there between 0.5 and 1.0? I'm more interested in the math behind it, and I need the answer for floats and doubles.

Upvotes: 13

Views: 7117

Answers (5)

Péter Joó
Péter Joó

Reputation: 41

Kerrek gave the best explanation :)

Just in case here is the code to play with other intervals too
http://coliru.stacked-crooked.com/a/7a75ba5eceb49f84

#include <iostream>
#include <cmath>

template<typename T>
unsigned long long int floatCount(T a, T b)
{
    if (a > b)
        return 0;

    if (a == b)
        return 1;

    unsigned long long int count = 1;

    while(a < b) {
        a = std::nextafter(a, b);
        ++count;
    }

    return count;
}

int main()
{
    std::cout << "number of floats in [0.5..1.0] interval are " << floatCount(0.5f, 1.0f);    
}

prints

number of floats in [0.5..1.0] interval are 8388609

Upvotes: 3

Kerrek SB
Kerrek SB

Reputation: 477160

For IEEE754 floats, this is fairly straight forward. Fire up the Online Float Calculator and read on.

All pure powers of 2 are represented by a mantissa 0, which is actually 1.0 due to the implied leading 1. The exponent is corrected by a bias, so 1 and 0.5 are respectively 1.0 × 20 and 1.0 × 2−1, or in binary:

      S    Ex + 127    Mantissa - 1                Hex

1:    0    01111111    00000000000000000000000     0x3F800000
      +     0 + 127    1.0

0.5:  0    01111110    00000000000000000000000     0x3F000000
      +    -1 + 127    1.0

Since the floating point numbers represented in this form are ordered in the same order as their binary representation, we only need to take the difference of the integral value of the binary representation and conclude that there are 0x800000 = 223, i.e. 8,388,608 single-precision floating point values in the interval [0.5, 1.0).

Similarly, the answer is 252 for double and 263 for long double.

Upvotes: 17

Daniel Fischer
Daniel Fischer

Reputation: 183918

A floating point number in IEEE754 format is between 0.0 (inclusive) and 0.5 (exclusive) if and only if the sign bit is 0 and the exponent is < -1. The mantissa bits can be arbitrary. For float, that makes 2^23 numbers per admissible exponent, for double 2^52. How many admissible exponents are there? For float, the minimal exponent for normalised numbers is -126, for double it's -1022, so there are

126*2^23 = 1056964608

float values in [0, 0.5) and

1022*2^52 = 4602678819172646912

double values.

Upvotes: 3

Chris Lutz
Chris Lutz

Reputation: 75419

This isn't an answer per-se, but you might get some milage out of the nextafter function. Something like this ought to help you answer your question, though you'll have to work out the math yourself:

float f = 0;
while(f < 0.5)
  {
    print("%f (repr: 0x%x)\n", f, *(unsigned *)&f);
    f = nextafterf(f, 0.5);
  }

Upvotes: 0

Scott Hunter
Scott Hunter

Reputation: 49848

For 0.0..0.5: you need to worry about exponents from -1 down to as low as possible, and then multiply how many you get time the number of distinct values you can represent in the mantissa.

For every value in that range, if you double it, you get a value in the range of 0.5..1.0. And doubling it means just bumping up the exponent.

You also need to worry about unnormalized numbers, where the mantissa isn't used to represent 1.x, but 0.x, and thus will all be in your lower range, but can't be doubled by bumping up the exponent (since a particular value of the exponent is used to indicate that the value is unnormalized).

Upvotes: 1

Related Questions