Плавающая точка в .NET - часть 1: принципы и форматы - Реальный код

ОГЛАВЛЕНИЕ


Реальный код

Почти все обсуждения до этого были теоретическими, и пора перейти к коду.

Мы будем придерживаться стандарта IEEE-754 и реализуем некоторые 'рекомендуемые функции', перечисленные в дополнении к стандартам для чисел с двойной точностью. Вот и они:

Функция Описание
CopySign(x, y) Копирует знак y в x.
Scalb(y, n) Подсчитывает y2n для целого значения n без подсчета 2n.
Logb(x) Возвращает несмещенную экспоненту x.
NextAfter(x, y) Возвращает значение следующего представимого соседа x со стороны y.
Finite(x) Возвращает "истину" если x является вещественным конечным числом.
Unordered(x, y) Возвращает "истину" если x и y не находятся в определенном порядке, то есть если либо x , либо y равны NaN.
Class(x) Возвращает класс плавающей точки числа x.

Мы не будем вдаваться в подробности, код легко понять. Но есть некоторые вещи, которые стоит обсудить.

Пробразование в и из двоичного представления

Большинство данных функций представляют некоторый вид операций по двоичному представлению чисел с плавающей точкой. Одинарное значение типа Single имеет то же число бит, что и int, а двойное значение (double) имеет то же число бит, как и long.

Для значений типа double, класс BitConverter содержит два полезных метода: DoubleToInt64Bits и Int64BitsToDouble. Как видно из названий, данные методы преобразуют double в форму 64-битного целого значения (integer). Не существует эквивалента для одинарных значений типа Single. К счастью, одной строкой небезопасного кода можно все исправить.

Нахождение следующего представимого соседа

Нахождение следующего представимого соседа числа с плавающей точкой, что является целью метода NextAfter, на самом деле довольно сложная операция. Нам необходимо работать с положительным и отрицательными, нормализованными и денормализованными числами, экспонентами и мантиссами, а также нулями, бесконечностью и не-числами!

К счастью, специальное свойство формата чисел с плавающей точкой нам поможет: значения сортируются в виде целых величин со знаком. Это означает то, что убрав знаковый бит на время, порядок чисел с плавающей запятой и их двоичное представление будут равны. Итак, все, что нам необходимо сделать для нахождения следующего соседа, так это увеличить или уменьшить двоичное представление на одно значение. Существуют некоторые специальные классы, но вся обработка экспонент будет уже выполнена.