2012-01-16 10 views
13

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

+1

подсказка: сколько бит используются для представления этого дробного диапазона? –

+1

Я не помню доказательство, но вы можете найти ответ в http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html или http: // с плавающей запятой .de /. – Crashworks

+0

не забудьте посчитать -0.0 :-) – franji1

ответ

13

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

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

 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 

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

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

+3

... и есть «0x3F000000» представимые одноточечные поплавки между «0.0» и «0.5», что составляет более 1 миллиарда. Ницца! – Arlen

1

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

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

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

+0

«Для каждого значения в этом диапазоне, если вы дважды, вы получите значение в диапазоне 0.5..1.0. " eh no вам нужно * добавить * 0.5, что означает, что все числа ниже 'ulp (0.5)' все будут одинаковыми (0.5), для диапазона 0.5..1 все показатели равны -1 –

+0

К сожалению, я думал о он в другом направлении (идет от диапазона 0.5..1.0 и сокращает вдвое все, что БУДЕТ все карты в нижний диапазон). –

+0

да, но у него не было бы ВСЕ чисел, особенно тех, которые <0.25 –

0

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

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

, прежде чем вы начнете эту попытку ** половина ** представляемых чисел в плавающей запятой между -1 и 1 для float, которая составляет 2 миллиарда (или 1 миллиард от 0 до 1), для двойного числа, которое это число * квадратично *, если вы начинаете считать, что вы будете ждать некоторое время –

+0

@ratchetfreak - Правда, но если вы не знаете основную математику (например, я), вы можете начать собирать образец с первых 20 максимум, а затем все, что вы действительно нужно знать, это начальная и конечная точки. Но да, лучше, если вы знаете математику за ней. –

2

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

126*2^23 = 1056964608 

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

1022*2^52 = 4602678819172646912 

double значение.

0

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

Только в случае здесь код, чтобы играть с другими интервалами тоже
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