Сколько разных чисел с плавающей точкой в ​​определенном диапазоне? - PullRequest
13 голосов
/ 16 января 2012

Сколько представимых чисел существует между 0.0 и 0.5? А сколько представимых чисел существует между 0.5 и 1.0? Меня больше интересует математика, стоящая за ней, и мне нужен ответ для floats и doubles.

Ответы [ 5 ]

14 голосов
/ 16 января 2012

Для поплавков IEEE754 это довольно просто.Запустите Online Float Calculator и читайте дальше.

Все чистые силы 2 представлены мантиссой 0, которая на самом деле 1.0 из-за подразумеваемого ведущего 1.показатель степени корректируется смещением, поэтому 1 и 0,5 соответственно равны 1,0 × 2 0 и 1,0 × 2 −1 или в двоичном виде:

      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

Счисла с плавающей запятой, представленные в этой форме, упорядочены в том же порядке, что и их двоичное представление, нам нужно только взять разность интегрального значения двоичного представления и сделать вывод, что 0x800000 = 2 23 ,т. е. 8 388 608 значений с плавающей запятой одинарной точности в интервале [0,5, 1,0).

Аналогично, ответ составляет 2 52 для double и 2 63 дляlong double.

3 голосов
/ 16 января 2012

Число с плавающей запятой в формате IEEE754 находится в диапазоне от 0,0 (включительно) до 0,5 (исключая), если и только если знаковый бит равен 0, а показатель степени равен < -1.Биты мантиссы могут быть произвольными.Для float это составляет 2^23 чисел на допустимую степень, для double 2 ^ 52.Сколько допустимых показателей есть?Для float минимальный показатель степени для нормализованных чисел равен -126, для double это -1022, поэтому в [0, 0.5) и

1022*2^52 = 4602678819172646912
имеются значения
126*2^23 = 1056964608

float

double значений.

1 голос
/ 16 января 2012

Для 0.0..0.5: вам нужно беспокоиться о показателях от -1 до минимально возможного, а затем умножить, сколько вы получите времени, на количество различных значений, которые вы можете представить в мантиссе.

Для каждого значения в этом диапазоне, если вы удвоите его, вы получите значение в диапазоне 0.5..1.0. А удвоение означает только увеличение показателя.

Вам также нужно беспокоиться о ненормализованных числах, где мантисса используется не для представления 1.x, а 0.x, и, таким образом, все будет в вашем нижнем диапазоне, но не может быть удвоена путем увеличения показатель степени (поскольку определенное значение показателя степени используется для указания того, что значение является ненормализованным).

0 голосов
/ 01 февраля 2016

Керрек дал лучшее объяснение:)

На всякий случай вот код для игры с другими интервалами тоже
http://coliru.stacked -crooked.com / а / 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);    
}

печать

number of floats in [0.5..1.0] interval are 8388609
0 голосов
/ 16 января 2012

Это не само по себе ответ, но вы можете получить некоторую прибыль из функции nextafter. Что-то вроде этого должно помочь вам ответить на ваш вопрос, хотя вам придется самому решать математику:

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