Хотелось бы узнать как правильно найти минимальное целое число не представимое в float и десятичной арифметике с заданной мантиссой и экспонентами(минимальная,максимальная)
1 Answers
В С константы
FLT_MANT_DIG
DBL_MANT_DIG
LDBL_MANT_DIG
из <float.h> дадут вам количество цифр в мантиссе соответствующего плавающего типа. Каждая цифра мантиссы - в базе FLT_RADIX (обычно 2). В С++ те же значения можно также получить через std::numeric_limits<type>::digits.
Соответственно, все целые числа, чей модуль не превосходит FLT_RADIXFLT_MANT_DIG должны быть представимы. А вот
FLT_RADIXFLT_MANT_DIG + 1
будет первым (минимальным) положительным целым не представимым в типе float.
Почему так? Так устроены плавающие типы. Если убрать не относящиеся к делу детали, то плавающее двоичное значение представляется по принципу
значение = мантисса * 2экспонента
Если полагать, что мантисса - целое число(1, то при любом значении экспоненты больше 0, в последовательности представимых таким способом целых чисел будут "дырки". Например, очевидно, что при экспоненте 1 представимы будут только четные числа. Непрерывная последовательность целых чисел возможна только при нулевой величине экспоненты, а также в точке перехода от экспоненты 0 к экспоненте 1.
Для экспоненты 0 диапазон ограничен диапазоном значений самой мантиссы. В типе float ширина мантиссы - 24 (это FLT_MANT_DIG). Соответственно диапазон представимых целых идет от 0 до 224-1. А затем, при переходе к экспоненте 1 мы получаем еще одно представимое целое число: 224. А вот следующим представимым целым числом при экспоненте 1 будет только 224+2. Так что число 224+1 - это первая "дырка" в последовательности представимых целых чисел.
Проверим
#include <assert.h>
#include <float.h>
#include <stdio.h>
int main()
{
static_assert(FLT_RADIX == 2, "Ya krevedko");
{
unsigned long long i = 1ull << FLT_MANT_DIG;
float f = i;
printf("%llu %f\n", i, f);
f = ++i;
printf("%llu %f\n", i, f);
}
{
unsigned long long i = 1ull << DBL_MANT_DIG;
double f = i;
printf("%llu %lf\n", i, f);
f = ++i;
printf("%llu %lf\n", i, f);
}
}
Вывод
16777216 16777216.000000
16777217 16777216.000000
9007199254740992 9007199254740992.000000
9007199254740993 9007199254740992.000000
Таким образом в IEEE 754 типа float первое непредставимое целое число - это 16777217, а для типа double - это число 9007199254740993.
Та же формула применима и к десятичным представлениям с плавающей точкой, построенным на тех же принципах.
1) В реальности в IEEE 754 все несколько по-другому. Мантисса - это двоичное число с точкой вида 1.000...0 шириной в 24 бита (т.е. 23 двоичных знака после точки), и соответственно идущие подряд целые числа будут представляться при значениях экспоненты до 23. А начиная со значения экспоненты 24 будут представляться уже только четные целые числа. Но на вышеприведенные рассуждения это не оказывает принципиального влияния. Принципиальный момент тут в любом случае один и тот же - непрерывный диапазон целых чисел определяется шириной мантиссы.
- 69,346
-
-
-
@AnT Есть формула для представления числа x = мантиссаоснование степенипоказатель степени. в питоне мантисса для float = 53 основание степени = 2 и возьмем максимальный показатель степени = 1024 получим совершенно другое число – Yopp Apr 09 '17 at 16:38
-
@Yopp Во-первых, ваш питоновский
floatс 53 битами в мантиссе - это, очевидно, Сишныйdouble. Во-вторых я не понимаю, что вы пытаетесь продемонстрировать, беря максимальный показатель степени. Да, получим совершенно другое число. И какой из этого следует вывод? Что вы этим хотите сказать? – AnT stands with Russia Apr 09 '17 at 17:26 -
sys.float_info.radix == 2(пример как число107.0в виде бит выглядит) – jfs Apr 09 '17 at 07:04