Сколько представимых чисел с плавающей запятой находится между 0.0
и 0.5
? И сколько представимых чисел с плавающей запятой находится между 0.5
и 1.0
? Меня больше интересует математика, лежащая в основе этого, и мне нужен ответ для floats
и doubles
.
Сколько различных чисел с плавающей запятой в определенном диапазоне?
Ответы (5)
Для поплавков IEEE754 это довольно просто. Запустите онлайн-калькулятор с плавающей запятой и продолжайте читать.
Все чистые степени двойки представлены мантиссой 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 sup >, т.е. 8 388 608 значений с плавающей запятой одинарной точности в интервале [0,5, 1,0).
Точно так же ответ: 2 52 для double
и 2 63 для long double
.
0x3F000000
представимые числа с плавающей запятой одинарной точности между 0.0
и 0.5
, что превышает 1 миллиард. Хороший!
- person Arlen; 16.01.2012
Число с плавающей запятой в формате 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,0..0,5: вам нужно позаботиться об экспонентах от -1 до минимально возможного, а затем умножить, сколько вы получите, на количество различных значений, которые вы можете представить в мантиссе.
Для каждого значения в этом диапазоне, если вы удвоите его, вы получите значение в диапазоне 0,5..1,0. А удвоение - это просто увеличение показателя степени.
Вам также нужно беспокоиться о ненормализованных числах, где мантисса используется не для представления 1.x, а для 0.x, и, таким образом, все они будут в вашем нижнем диапазоне, но не могут быть удвоены путем увеличения показателя степени (поскольку конкретное значение показателя степени используется, чтобы указать, что значение ненормализовано).
ulp(0.5)
станут одинаковыми (0,5), для диапазона 0,5..1 все показатели равны -1
- person ratchet freak; 16.01.2012
Сам по себе это не ответ, но вы можете получить некоторую информацию из nextafter
функция. Что-то вроде этого должно помочь вам ответить на ваш вопрос, хотя вам придется вычислить математику самостоятельно:
float f = 0;
while(f < 0.5)
{
print("%f (repr: 0x%x)\n", f, *(unsigned *)&f);
f = nextafterf(f, 0.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