Какое первое целое число, которое IEEE 754 не может точно представить?


164

Для ясности, если я использую язык, который реализует плавающие объекты IEE 754, и я объявляю:

float f0 = 0.f;
float f1 = 1.f;

... а затем распечатать их обратно, я получу 0,0000 и 1,0000 - точно.

Но IEEE 754 не способен представлять все числа вдоль реальной линии. Близко к нулю, «пробелы» малы; по мере того как вы уходите дальше, промежутки увеличиваются.

Итак, мой вопрос: для числа с плавающей запятой IEEE 754, какое первое (ближайшее к нулю) целое число не может быть точно представлено? На данный момент меня интересуют только 32-битные числа с плавающей запятой, хотя мне было бы интересно услышать ответ на 64-битную версию, если кто-то ее даст!

Я думал, что это будет так же просто, как вычислить 2 bits_of_mantissa и добавить 1, где bits_of_mantissa - это количество битов, которое предоставляет стандарт. Я сделал это для 32-разрядных операций с плавающей запятой на моей машине (MSVC ++, Win64), и все выглядело нормально.


Зачем вы добавили один, если вы хотели непредставительный номер? А какой номер ты использовал или получил? И это домашнее задание? И в заголовке вашего вопроса написано "целое число", а в вашем вопросе - "плавать".
2010 г.

5
Потому что я полагал, что максимальная мантисса даст мне наибольшее представимое число. 2 ^ 22. Нет, это вопрос любопытства. Я всегда чувствовал себя виноватым, помещая ints в float, даже когда я знаю, что рассматриваемый int всегда будет очень маленьким. Я хочу знать, каков верхний предел. Насколько я могу судить, заголовок и вопрос одинаковы, просто сформулированы по-разному.
Флуми



1
@KyleStrand вернулся ^ 2. Я не знаю, почему один показался мне более правильным, чем другой в то время. Теперь они оба кажутся неловкими по сравнению с «… это число бит…»
Паскаль Куок

Ответы:


211

2 биты мантиссы + 1 + 1

+1 в показателе степени (биты мантиссы + 1) объясняется тем, что, если мантисса содержит abcdef...число, которое она представляет, фактически 1.abcdef... × 2^eобеспечивает дополнительный неявный бит точности.

Следовательно, первое целое число, которое не может быть точно представлено и будет округлено:
For float, 16 777 217 (2 24 + 1).
За 9 double007 199 254 740 993 (2 53 + 1).

>>> 9007199254740993.0
9007199254740992

Я объявил floatи установил его равным 16 777 217. Но когда я распечатал его с помощью, coutэто привело к 16 777 216. Я использую C++. Почему я не могу получить 16 777 217?
нитрат натрия

18
@sodiumnitrate Проверьте название вопроса. 16777217 - первое целое число, которое не может быть точно представлено.
Kennytm

Хорошо, спасибо. Я запутался, извините за это. У меня есть еще один вопрос: после 16777216 не должно ли следующее целое число, которое представимо, быть 2 * 16777216? Когда я запускаю аналогичную программу, я получаю 16777218, добавляя 2 к 16777126.
Нитрат натрия

5
Следующее целое число действительно 16777218, потому что теперь 2 становится последней значащей двоичной цифрой.
Кеннитм

6
В C ++, это (1 << std::numeric_limits<float>::digits) + 1, и в C, (1 << FLT_MANT_DIG) + 1. Первый вариант хорош тем, что может быть частью шаблона. Не добавляйте +1, если вы просто хотите наибольшее представимое целое число.
Генри Шрайнер,

38

Наибольшее значение, представляемое n- битным целым числом, равно 2 n -1. Как отмечалось выше, значение a floatимеет 24 бита в значении, и это может показаться, что 2 24 не подходят.

Однако .

Степени 2 в диапазоне показателя в точности представимы как 1,0 × 2 n , так что 2 24 может соответствовать, и, следовательно, первое непредставимое целое число для floatравно 2 24 +1. Как указано выше. Очередной раз.


1
Это ясно объяснило «дополнительный неявный бит точности» другой части. Спасибо.
chappjc
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.