Сколько представимых поплавков существует между 0.0
и 0.5
? И сколько представимых поплавков существует между 0.5
и 1.0
? Меня больше интересует математика, и мне нужен ответ для floats
и doubles
.
Сколько различных чисел с плавающей запятой в определенном диапазоне?
Ответ 1
Для поплавков IEEE754 это довольно прямолинейно. Запустите Online Float Calculator и прочитайте дальше.
Все чистые степени 2 представлены мантиссой 0
, которая на самом деле 1.0
из-за предполагаемого ведущего 1. Экспонента исправляется смещением, поэтому 1 и 0,5 соответственно равны 1.0 & times;  , 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