IEEE 754: как именно это работает? - PullRequest
4 голосов
/ 10 августа 2011

Почему следующий код ведет себя так же, как в C?

float x = 2147483647; //2^31
printf("%f\n", x); //Outputs 2147483648

Вот мой мыслительный процесс:

2147483647 =   0      1001 1101      1111 1111 1111 1111 1111 111

   (0.11111111111111111111111)base2 = (1-(0.5)^23)base10
=> (1.11111111111111111111111)base2 = (1 + 1-(0.5)^23)base10 = (1.99999988)base10

Поэтому, чтобы преобразовать нотацию IEEE 754 обратно в десятичную форму: 1.99999988 * 2^30 = 2147483520

Так что технически программа на С должна распечатать 2147483520, верно?

Ответы [ 4 ]

3 голосов
/ 10 августа 2011

Представляемое значение будет 2147483647. Следующие два значения, которые можно представить таким образом, это 2147483520 и 2147483648.

Поскольку последний ближе к непредставимому «идеальному», он используется: в плавающей точке значения округляются, а не усекаются.

1 голос
/ 14 августа 2011
2147483647 = 2^31 - 1 = +1 * 2^30 * 1.1111 1111 1111 1111 1111 1111 1111 11

При кодировании этого числа в формате IEEE 754-1985 с одинарной точностью, значение и округляется правильно. Для режима округления округление до ближайшего четного (режим округления по умолчанию) это означает, что оно округляется.

Перед округлением:

exponent = 30, significand = 1.1111 1111 1111 1111 1111 1111 1111 11

После округления значения до 23 знаков после запятой:

exponent = 30, significand = 10.0000 0000 0000 0000 0000 000

После нормализации:

exponent = 31, significand = 1.0

Кодируется в формате с одинарной точностью:

1 | 10011110 | 00000000000000000000000
1 голос
/ 10 августа 2011

Форматы с плавающей точкой часто находятся в «нормализованной форме», где наиболее значимый бит мантиссы всегда равен 1. Поскольку он всегда равен 1, вам не нужно использовать бит для его хранения. Поэтому при декодировании такого числового представления вам необходимо добавить обратно 1 в верхней части.

1 голос
/ 10 августа 2011

Стандарт доступен здесь . Возможно, вам придется его купить, поскольку IEEE (и другие подобные организации) в основном зарабатывают деньги, продавая стандарт, чтобы покрыть свои расходы на сборку, лоббирование и принятие стандартов.

Биты означают только то, что кто-то определяет им как

«Когда я использую слово, - сказал Шалтай-Болтай довольно презрительным тоном, - это означает только то, что я выбрал, чтобы иметь в виду - ни больше, ни меньше ". вопрос, "сказала Алиса," можете ли вы сделать так, чтобы слова означали так много разные вещи. "" Вопрос в том, "сказал Шалтай-Болтай," который должен быть хозяином - и все. "(Зазеркалье, глава 6)

В этом случае IEEE решил, что означают эти биты, и причина того, что флаг printf% f выводит соответствующее соответствующее человеческое представление, связана с тем, что флаг также следует тому же стандарту.

Иногда вам удается преобразовать биты в другой тип данных (например, int) и распечатать «другое» представление этих битов. C поймает много обычных продвижений по номерам, но вы можете запутать это, как правило, с помощью назначения указателя неправильного типа на правильный адрес (и разыменования их).

Обратите внимание, что, пока вы выполняете математику вручную, не гарантируется, что реальное оборудование выполнит математику точно так же, как вы. С целочисленной математикой в ​​представлении намного больше точности, но с математикой с плавающей запятой, то, как вы округляете число, имеет большое значение в выводе. Это даже не упоминает ошибки с плавающей запятой, которые иногда записывались в системы (к счастью, не часто).

...