Увеличить вдвое до следующего ближайшего значения? - PullRequest
4 голосов
/ 02 сентября 2011

Это не вопрос для реального проекта; Мне только любопытно.

Мы можем увеличить int, используя оператор приращения (i++). Вы можете определить эту операцию как:
Это увеличивает переменную с ближайшим значением до i. Который в этом случае просто +1.

Но я думал об определении числа двойных значений, доступных в определенном диапазоне, в соответствии с системой IEEE 754-2008. Я мог бы настроить график, который демонстрирует эти суммы в некоторых диапазонах и посмотреть, как он уменьшается.

Я полагаю, что должен быть побитовый способ увеличения двойного значения до ближайшего значения, большего, чем исходный двойной.

То, что я нашел в Википедии , это:

Примеры двойной точности

0x 3ff0 0000 0000 0000   = 1
0x 3ff0 0000 0000 0001   = 1.0000000000000002, the next higher number > 1
0x 3ff0 0000 0000 0002   = 1.0000000000000004

Здесь вы можете видеть, что следующее большее число получается путем увеличения двоичного содержимого. Но я не думаю, что это будет работать, поскольку двойная схема выглядит так:

enter image description here

Я думаю, что нужно сделать что-то еще, чтобы сделать наименьшее увеличение, когда все дробные биты установлены в единицу.

Может быть, у этой операции есть имя? Интересные ссылки?
Любая информация приветствуется: D

Спасибо

Ответы [ 2 ]

4 голосов
/ 03 сентября 2011

Здесь вы можете видеть, что следующее большее число получается путем увеличения двоичного содержимого. Но я не думаю, что это будет работать, поскольку двойная схема выглядит так:

[изображение опущено]

Я думаю, что нужно сделать что-то еще, чтобы сделать наименьшее увеличение, когда все биты дроби установлены в единицу.

В первом приближении, да, это работает .

Рассмотрим нормализованное положительное число: это значение m * 2 e , где 1 <= <em>m <2, т.е. <em>m = 1.xxxxxxx (в двоичном виде). «1» перед двоичной точкой опускается в сохраненном значении, поэтому часть «дроби» (или «мантиссы» или «значимого») хранимого значения состоит из битов после двоичной точки.

Давайте представим, что в дробной части только 4 бита, а не 52: сохраненное значение 1111 (двоичное) представляет в дробной части m = 1.1111 (двоичное). Обрабатывая это как целое число и увеличивая его, вы получите дробную часть 0000 с переносом.

Но перенос входит в показатель степени, который увеличивает его. Совершенно верно: после 1.1111 * 2 e следующее число, которое мы ожидаем, будет 10.0000, что действительно 1.0000 * 2 e + 1 !


Я сказал «в первом приближении» ... преобразование представления в целое число, приращение и обратное преобразование в двойное отлично работает для положительных нормализованных чисел. Это также работает для положительных денормализованных чисел (меньше наименьшего нормализованного числа; они имеют показатель степени 0, а бит, который обычно скрыт, является явным).

Это работает для отрицательных чисел, если ваше целочисленное представление также является величиной знака; чего обычно не будет. Для более типичного дополнения к двум вы должны вычесть один, чтобы «увеличить» отрицательный двойной.

Наконец, в конечном итоге вы переполните наибольшее нормализованное число и увеличите показатель степени до бесконечности и диапазона NaN.

Есть интересная статья, которая освещает это здесь .

2 голосов
/ 02 сентября 2011

В C99 есть nextafter (3) и друзья.

Если вы хотите сделать это вручную, я думаю, что наиболее просто иметь одно целое число для представления значения и одно для показателя степени.

Если вы избегаете субнормалей и увеличиваете положительные числа, когда значимое достигает 2 << 52, вы должны увеличить показатель степени и разделить значимое на 2. </p>

...