Подтвердить что ты не робот

Сколько различных чисел с плавающей запятой в определенном диапазоне?

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

4b9b3361

Ответ 1

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

Все чистые степени 2 представлены мантиссой 0, которая на самом деле 1.0 из-за предполагаемого ведущего 1. Экспонента исправляется смещением, поэтому 1 и 0,5 соответственно равны 1.0 & times; &nbsp, 2 0 и 1.0 & times; 2 & minus; 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].

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

Ответ 2

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

126*2^23 = 1056964608

float значения в [0, 0.5) и

1022*2^52 = 4602678819172646912

double.

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

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

На всякий случай, здесь есть код для воспроизведения с другими интервалами.
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);    
}

печатает

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