Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

9899 - Полный справочник по языку Си - Выпуск 5: Представление плавающих значений


Информационный Канал Subscribe.Ru

"9899"
Полный справочник по языку Си

К читателям

"9899" взрослеет. Количество подписчиков приближается к трем тысячам. Пора подвести некоторые итоги.

Появилось полное, развитое оформление. Выпуски получили содержания, благодаря которым можно быстро сориентироваться в объемном материале, шрифтовые выделения стали богаче и вразумительнее, ссылку обратной связи с редакцией больше не нужно искать где-то внизу страницы.

Мы также значительно усовершенствовали саму технологию подготовки выпусков. И в части верстки, и в части подхода к разработке контента.

Основной шрифт стал крупнее. Странички выпусков теперь можно без искажений просматривать и в Internet Explorer, и в Netscape Navigator, и в Mozilla. В любом из этих браузеров вы сможете без проблем выбрать подходящий размер шрифта.

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

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

Если вам необходимы консультации, касающиеся тонкостей языков Си и Си++, которые могут существенно влиять или уже влияют на ваши проектные решения, если есть необходимость решать нетривиальные вопросы, связанные с разработкой интерфейсов, организацией структур данных, оценкой переносимости существующих проектов, организацией работы с памятью, особенностями различных диалектов Си и Си++, которые вы используете или даже с разработкой бизнес-процессов в части грамотного версионинга и обеспечения клиентской преемственности разрабатываемых вами программных компонент – мы всегда будем рады помочь вам. Пожалуйста, обращайтесь.

На этом все, не будем более томить ожиданием (ведь плох тот программист, которого не зажигают слова о представлении данных на абстрактной машине).

С уважением,
редакция рассылки "9899"

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

Модель чисел с плавающей точкой

Модель чисел с плавающей точкой в языках Си и Си++ – это способ описать представление и поведение таких чисел в процессе вычисления выражений. Это означает, что в конкретной реализации плавающая арифметика может быть устроена иначе, однако она обязана отвечать требованиям модели, изложенным в [C99] и [C++].

Требования модели распространяются на плавающие типы float (представление с условно одинарной точностью), double (представление с условно двойной точностью) и long double (представление с расширенной точностью). Требования к представлениям значений комплексных и мнимых типов (это типы доменов _Complex и _Imaginary, определенных в [C99]) опираются на эту модель.

Объектные представления

Важным обстоятельством является то, что модель плавающей арифметики Си и Си++ не определяет объектных представлений для данных плавающих типов. Оговорено только, что такие представления могут содержать padding-биты и (или) байты, не участвующие в образовании арифметических значений и никак не влияющие на их характеристики. В остальном модели оперируют исключительно характеристиками плавающих чисел.

История модели

Сама модель чисел с плавающей точкой Си и Си++ позаимствована из практики комитета по стандартизации языка Фортран, что было вполне оправдано, учитывая большой опыт комитета в этой области.

Эта модель была адаптирована для наиболее общей поддержки самых распространенных представлений чисел с плавающей точкой. К примеру, она допускает представление мантисс и экспонент и в форме "знак и модуль" (sign and magnitude), и в форме дополнения до двух (two's complement), однако исключает возможность логарифмической реализации.

Кроме того, комитет по стандартизации языка Си попытался "приспособить" [IEEE 754] (базовый международный стандарт, определяющий поведение и представление плавающих чисел) путем непринятия любых ограничений, которые конфликтуют с этим стандартом. Фактически, речь шла о некотором расширении стандарта IEEE с тем, чтобы дать наиболее универсальную спецификацию модели. Подробнее о стандартах говорится ниже, в специальном разделе.

Значения плавающих типов

Итак, все характеристики значений плавающей точкой определены в языках Си и Си++ в терминах специальной модели, которая описывает представление и поведение чисел с плавающей точкой, а также описывает значения, позволяющие программе выяснить эти характеристики для каждой конкретной реализации (например, машинное эпсилон для чисел типа double можно взять как значение макроса DBL_EPSILON, определяемого в стандартном заголовке <float.h>).

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

s число +1 или -1 обозначает знак числа с плавающей точкой;

b целое число, большее 1 основание мантиссы (significand base) и степень представления экспоненты (radix of exponent representation). Параметр b одинаков для всех плавающих типов;

e целое число между emin и emax включительно – экспонента (показатель) числа, где emin и emax соответствуют типу этого числа;

p количество значащих цифр по основанию b, соответствующее типу числа;

fk целые числа, меньшие b сами эти значащие цифры.

Согласно модели, нормализованное плавающее число с арифметическим значением x (имеет f1 > 0, если x != 0) определяется следующим образом:

x = s * be * SUM pk = 1 (fk * b-k)

Субнормальное плавающее число (subnormal floating-point number) имеет арифметическое значение x, отличное от 0, e = emin и f1 = 0. Денормализованное плавающее число (unnormalized floating-point number) также имеет арифметическое значение, отличное от 0, но e > emin и f1 = 0.

Субнормальные и денормализованные числа могут использоваться реализацией произвольным образом. К примеру, субнормальные числа могут быть использованы и действительно иногда используются для расширения динамического диапазона.

Нечисловые плавающие значения включают в себя бесконечные величины и т. н. NaN'ы (Not-a-Numbers, не-числа). Среди последних реализация может поддерживать и тихие NaN'ы (quiet NaNs), которые не вызывают исключений (floating-point exceptions) когда выступают одним из операндов вычисляемой операции, и т. н. сигнализирующие NaN'ы (signaling NaNs), которые – напротив – вызывают исключения в таких случаях.

Согласно [IEC 60559] (см. ниже), главное назначение тихих NaN'ов – это задание значения по умолчанию для отношения 0.0 / 0.0, и эта идея целиком поддержана в [C99].

Другие применения NaN'ов могут быть следующими. Во-первых, в составных частях NaN'а можно кодировать вспомогательную (служебную) информацию. Во-вторых, сигнализирующие NaN'ы хорошо подходят для заполнения неинициализированных объектов плавающих типов, поскольку случай использования любого из этих объектов без предварительной инициализации тут же будет обнаружен.

Составные части плавающих значений

Под составными частями плавающих чисел понимают их мантиссы (дробные части) и экспоненты (показатели), соответствующие некоторому нормированному представлению этих чисел в памяти. Для нечисловых плавающих значений ссылки на их составные части следует понимать как ссылки на битовые поля, соответствующие мантиссам и экспонентам в объектных представлениях этих значений.

В Си и Си++ определены функции семейства frexp из стандартного заголовка <math.h>, разбивающие числа типов float, double и long double на составные части. Отличные от нуля числа будут разбиты ими на дробные части в диапазоне [0.5, 1) и целые (int) экспоненты, взятые из расчета представления числа по основанию 2 независимо от действительного основания представления этих чисел в памяти.

Знаковые нули

[C99], идя навстречу существующей практике, не требует обязательной поддержки реализацией плавающей арифметики отрицательных нулей. Так, например, на машинах VAX представление, соответствующее отрицательному нулю используется как одно из нечисловых плавающих значений.

Непредставимость десятичных дробей

Большинство современных платформ представляют мантиссы плавающих чисел в форме конечных двоичных дробей. Это значит, что скорее всего на вашей платформе некоторые десятичные дроби не смогут быть представлены точно.

Часть таких чисел не сможет быть представлена из-за ограниченной ширины мантиссы, которая всегда конечна и не всегда достаточна. Часть – из-за принципиальной, математической невозможности записать десятичную дробь в двоичной форме, поскольку не каждую десятичную дробь можно разложить на конечную сумму последовательных отрицательных целых степеней двойки.

На деле, непредставимые десятичные дроби получают одно из двух ближайших представимых значений – меньшее или большее него. При этом точность такого приближения зависит от типа числа. Как следствие, одни и те же непредставимые десятичные дроби разных плавающих типов будут иметь разные арифметические значения. Например, плавающие константы 0.1 (типа double) и 0.1f (типа float) не будут равны.

Важно понимать, что непредставимые десятичные дроби – это не особые, редкие или "умные" числа. Речь идет о самых обычных дробях – таких как 0.1 или 0.7. К примеру, из всех чисел в диапазоне [0, 1] с одинаковым количеством знаков после десятичной точки лишь не более пятой части могут быть точно представлены в двоичной форме.

Характеристики плавающих типов

Максимальное представимое число, минимальное представимое число и машинное эпсилон – основные характеристики любой машинной арифметики, так или иначе используемые практически во всех реализациях алгоритмов численного анализа.

Максимальное и минимальное представимые числа определяют диапазон представимых чисел, или динамический диапазон арифметики. В плавающей арифметике этот диапазон определяется шириной (т. е. количеством разрядов) экспоненты. Машинное эпсилон выражает точность представления чисел и зависит от ширины мантиссы.

Все перечисленные ниже характеристики, определяемые в стандартном заголовке <float.h> соответствуют действительному аппаратному представлению плавающих чисел в памяти (но только не представлению в модели чисел с плавающей точкой, их представлению в регистрах процессора или представлению в терминах операций). Кроме того, эти характеристики заведомо справедливы для всех операций над плавающими числами, а также для всех стандартных функций, работающих с ними.

Типы

Предельные представимые значения

действительные

минимальные

float

FLT_MIN

1e-37

FLT_MAX

1e+37

double

DBL_MIN

1e-37

DBL_MAX

1e+37

long double

LDBL_MIN

1e-37

LDBL_MAX

1e+37

Гарантировано, что множество значений типа float это подмножество значений типа double, которое, в свою очередь, является подмножеством значений типа long double. Это важно уже хотя бы из-за неявных продвижений плавающих значений, которые могут иметь место, например, в арифметических операциях, но не должны приводить ни к потере точности, ни к ошибкам выхода за границы представимых значений типа.

Основание представления


// база, основание системы счисления разрядов
// мантиссы и экспоненты (значение b)

#define FLT_RADIX b  // для всех типов

Макрос определяется как целое число, не меньшее 2.

Ширина мантиссы


// количество цифр по основанию b (значение p)

#define FLT_MANT_DIG p-float
#define DBL_MANT_DIG p-double
#define LDBL_MANT_DIG p-ldouble

Имена макросов образованы как сокращения от "float mantissa digits" (разряды, или цифры мантиссы плавающего типа), однако сейчас стандарт вместо мантиссы использует более точный термин – significand (значащая часть).

Значения этих макросов жестко связаны со значениями макросов FLT_DIG, DBL_DIG и LDBL_DIG (см. ниже).


// количество десятичных цифр для плавающего типа с
// наибольшим количеством значащих цифр по основанию b
// (widest floating type), которые могут быть округлены до
// плавающего числа с n десятичными цифрами и преобразованы
// обратно без изменения значения

// вычисляется как p-max * log10(b), если b - это степень
// десятки или, иначе, как ceil(1 + p-max * log10(b))

#define DECIMAL_DIG n  // для самого широкого типа

Макрос определяется как целое число, не меньшее 10.

Если в реализации используется формат extended (по [IEC 60559] с 64-битовой точностью), DECIMAL_DIG должен быть равен по крайней мере 21. Если double (53 бита) – это самый широкий плавающий тип, то DECIMAL_DIG должен быть равен по крайней мере 17 (в отличие от LDBL_DIG и DBL_DIG, которые равны 18 и 15 соответственно для этих форматов.)


// целое число q, такое, что любое плавающее число с q
// десятичными цифрами может быть преобразовано с округлением
// в плавающее число с p разрядами по основанию b и
// обратно без изменения этих q десятичных цифр

// вычисляется как p * log10(b), если b - это степень
// десятки или, иначе, как floor((p - 1) * log10(b))

#define FLT_DBG q-float  // не меньше 6
#define DBL_DIG q-double  // не меньше 10
#define LDBL_DIG q-ldouble  // не меньше 10

Для значений этих макросов всегда справедливо, что FLT_DBG <= DBL_DIG <= LDBL_DIG.

Предельные представимые значения


// наименьшее отрицательное целое число e-min, такое,
// что p, возведенное в эту степень есть нормализованное
// плавающее число

#define FLT_MIN_EXP e-min-float
#define DBL_MIN_EXP e-min-double
#define LDBL_MIN_EXP e-min-ldouble

Значения этих макросов жестко связаны со значениями макросов FLT_MIN_10_EXP, DBL_MIN_10_EXP и LDBL_MIN_10_EXP.


// наименьшее отрицательное целое число e10-min, такое,
// что 10, возведенное в эту степень есть нормализованное
// плавающее число

// вычисляется как ceil(log10(pow(b, (e-min - 1))))

#define FLT_MIN_10_EXP e10-min-float  // не больше -37
#define DBL_MIN_10_EXP e10-min-double  // не больше -37
#define LDBL_MIN_10_EXP e10-min-ldouble  // не больше -37

Для значений этих макросов всегда справедливо, что FLT_MIN_10_EXP >= DBL_MIN_10_EXP >= LDBL_MIN_10_EXP.


// наибольшее положительное целое e-max, такое, что p,
// возведенное в эту степень есть нормализованное
// плавающее число

#define FLT_MAX_EXP e-max-float
#define DBL_MAX_EXP e-max-double
#define LDBL_MAX_EXP e-max-ldouble

Значения этих макросов жестко связаны со значениями макросов FLT_MAX_10_EXP, DBL_MAX_10_EXP, LDBL_MAX_10_EXP.


// наибольшее положительное целое e10-max, такое, что 10,
// возведенное в эту степень есть нормализованное
// плавающее число

// вычисляется как
// floor(log10((1 - pow(b, -p)) * pow(b, e-max)))

#define FLT_MAX_10_EXP e10-max-float  // не меньше +37
#define DBL_MAX_10_EXP e10-max-double // не меньше +37
#define LDBL_MAX_10_EXP e10-max-ldouble  // не меньше +37

Для значений этих макросов всегда справедливо, что FLT_MAX_10_EXP <= DBL_MAX_10_EXP <= LDBL_MAX_10_EXP.


// максимальное представимое плавающее число x-max

// вычисляется как (1 - pow(b, -p)) * pow(b, e-max)

#define FLT_MAX x-max-float  // не меньше 1e+37
#define DBL_MAX x-max-double  // не меньше 1e+37
#define LDBL_MAX x-max-ldouble  // не меньше 1e+37

Для значений этих макросов всегда справедливо, что FLT_MAX <= DBL_MAX <= LDBL_MAX.


// минимальное нормализованное положительное
// плавающее число x-min

// вычисляется как pow(b, e-min - 1)

#define FLT_MIN x-min-float  // не больше 1e-37
#define DBL_MIN x-min-double  // не больше 1e-37
#define LDBL_MIN x-min-ldouble  // не больше 1e-37

Машинное эпсилон


// арифметическая разница eps между числом 1 и наименьшим
// значением, большим 1, которое представимо в плавающем типе

// вычисляется как pow(b, (1 - p))

#define FLT_EPSILON eps-float  // не меньше 1e-5
#define DBL_EPSILON eps-double  // не меньше 1e-9
#define LDBL_EPSILON eps-ldouble  // не меньше 1e-9

Для значений этих макросов всегда справедливо, что FLT_EPSILON >= DBL_EPSILON >= LDBL_EPSILON.

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

Стандарты IEEE 754, 854, IEC 559/60559 и LIA-1

Стандарт ANSI/IEEE 754:1985 ([IEEE 754]) определяет требования к реализации двоичной плавающей арифметики, беря за основу формат, использовавшийся на машинах VAX и PDP-11. Более поздний ANSI/IEEE 854:1987 ([IEEE 854]) обобщает прежний "двоичный" стандарт допуская дополнительно, кроме двоичного, десятичное основание (radix) представлений мантиссы и экспоненты и произвольную длину машинного слова. Еще позднее требования этих стандартов были отражены в нормативе IEC 60559:1989 ([IEC 60559], ранее обозначавшемся как IEC 559:1989).

ISO/IEC 10967-1 ([LIA-1]) – еще более общий стандарт, определяющий единые требования к арифметике для различных языков – дополнительно включает описание целочисленных типов и различных реализаций плавающей арифметики.

Каждый из этих стандартов так или иначе поддерживается Си и Си++.

Стандартные представления значений

В большинстве современных платформ, таких как Intel x86 и почти всех RISC-системах, включая IBM Power и Power PC, Compaq и DEC Alpha, HP PA-RISC, Motorola 68K и 88K, SGI (MIPS) серии R, Sun SPARC и других, аппаратно реализована плавающая арифметика, соответствующая [IEC 60559].

Согласно [C99], реализации, удовлетворяющие требованиям этого стандарта, определяют макросы __STDC_IEC_559__ для плавающей вещественной и __STDC_IEC_559_COMPLEX__ для плавающей комплексной арифметики.

[IEC 60559] определяет два основных представления (формата, в терминологии этого стандарта) плавающих чисел – с одинарной (single format, тип float) и двойной (double format, тип double) точностью.

Форматы

Предельные представимые значения

действительные

минимальные

single

1.2e-38

1.2e-38

3.4e+38

3.4e+38

double

2.2e-308

2.2e-308

1.8e+308

1.8e+308

double-extended

-

3.4e-4932

-

1.2e+4932

Еще одно представление, называемое представлением с расширенной точностью (double-extended format), используется для хранения промежуточных результатов вычислений. При этом значения типа long double в соответствующей (conforming) реализации должны быть представлены либо в формате double-extended, либо в формате double, либо в любом другом формате, выбранном на усмотрение производителя. В последнем случае выбранный формат должен иметь бoльшую точность, чем точность формата double и иметь динамический диапазон по меньшей мере равный диапазону формата double.

Формат

Размер

Мантисса

Экспонента

single

32 бита

23 бита

8 битов

double

64 бита

52 бита

11 битов

double-extended

>= 80 битов

>= 64 битов

>= 15 битов

При оценке точности форматов [IEC 60559] необходимо иметь в виду следующее. Согласно этому стандарту, для представления всех вещественных чисел кроме нуля используется нормализованная форма, при которой старший разряд мантиссы (f0) равен единице. Поскольку значение старшего разряда заведомо известно, в представлении он опускается, а в памяти хранятся только младшие разряды. Таким образом, мантисса, если она не равна нулю, всегда принадлежит диапазону [1, 2). (Тем не менее, стандартные функции семейства frexp, возвращающие составные части плавающих чисел всегда дают значение ненулевой мантиссы в диапазоне [0.5, 1).)

Важным замечанием относительно арифметики [IEC 60559] является то, что стандарт не дает гарантий идентичности представления результатов на различных реализациях арифметики. Одна из возможных причин – различия в реализациях преобразований плавающих констант из десятичной формы в двоичную (стандарт не определяет строго точность, с которой должны выполняться такие преобразования).

Другой возможной причиной могут стать различные типы промежуточных значений (например, при передаче плавающего числа в вызываемую функцию). Несмотря на то, что стандарт требует правильного округления для каждого типа, в нем нет требований предоставления пользователю возможности выбирать типы промежуточных значений. Обычно так и случается – типы промежуточных значений неизменны и выбираются производителем на собственное усмотрение.

Таким образом, даже на строго соответствующих [IEC 60559] реализациях и во всех случаях, когда ширина используемых плавающих типов различна результаты вычислений могут отличаться, независимо от грамотности составления кода.

Кроме того, поскольку динамический диапазон формата double extended не фиксирован, значения типа long double, даже если он реализован в этом формате и в строгом соответствии с [IEC 60559], не будут переносимы в общем случае.

Представления всех арифметических типов в Си и Си++ совместимы с [LIA-1]. При этом, если реализация типов float, double и long double поддерживает значения underflow, floating_underflow и undefined, специфицированные [LIA-1], она является строго соответствующей этому стандарту.

Реализации, поддерживающие плавающие форматы [IEC 60559] и операции вкупе с флагом статуса (IEC 60559 status flag) и trap-представлениями, имеют совместимые с [LIA-1] типы.

Сравнения в стандартных представлениях

Замечательным свойством форматов single и double является их т. н. "лексикографическая упорядоченность". Это означает, что если два плавающих числа в одном и том же формате связаны некоторым отношением сравнения (например, x <= y), то и их объектные представления, будучи интерпретированными как целые числа в форме "знак и модуль", будут связаны тем же отношением. Такое свойство легко заподозрить, если взглянуть на представления характерных плавающих чисел. Например, наибольшее положительное нормализованное число в формате double имеет целочисленное значение 0x7fef ffff ffff ffff (пробелы вставлены для лучшей читаемости), а наименьшее положительное нормализованное – 0x0010 0000 0000 0000.

"Секрет" этого свойства в выбранном порядке следования полей знака, экспоненты и мантиссы. Однобитовое поле знака, занимающее самую левую (старшую) позицию определяет знак плавающего числа – так же как и в числе в форме "знак и модуль". Затем следует поле экспоненты, представленное как беззнаковое целое и, фактически, определяющее положение первого значащего разряда. Следовательно, сравнение экспонент как целых, если они не равны, однозначно дает заключение об арифметическом отношении чисел. Последним следует поле мантиссы, содержащее значащие разряды, которые также могут быть подвергнуты целочисленному сравнению, если и знаки, и значения экспонент совпадают.

Как следствие, аппаратные реализации арифметики [IEC 60559] обычно не нуждаются в специальных операциях быстрых сравнений, сортировки массивов и поиска в упорядоченных массивах плавающих чисел. Единственным неудобством может стать необходимость правильно загрузить представления плавающих чисел в целые на машинах с обратным порядком слов.

Порядок слов в стандартных представлениях

Действительно, IEEE- и IEC-стандарты не ограничивают разнообразие поддерживаемых платформ каким-либо определенным порядком слов (endianness). Так, например, все PC на базе архитектур Intel, на которых младшие байты размещаются первыми, т. е. платформы little-endian, используют IEEE-совместимую плавающую арифметику. Sun и NeXT реализуют то же на big-endian-архитектурах.

Стандартные нечисловые значения

[IEC 60559], как и [C99], не определяет поведение сигнализирующих NaN'ов и бесконечностей. Термин NaN в этом документе соответствует понятию тихого NaN'а в [C99].

В случае поддержки реализацией арифметики [IEC 60559], макросы NAN и INFINITY и функция nan из заголовка <math.h> означают NaN'ы и бесконечности, соответствующие определениям этого стандарта. (Полная поддержка сигнализирующих NaN'ов подразумевает поддержку представлений, называемых restartable и optional traps, специфицированных в [IEC 60559].)

Нестандартные форматы плавающих значений

Смысл их упоминания здесь в том, чтобы дать общее представление о различиях среди наиболее важных с коммерческой точки зрения форматах. Подробные и точные спецификации следует, разумеется, искать у производителей и поставщиков соответствующих платформ.

Формат IBM

Формат

Размер

Мантисса

Экспонента

IBM floating-point

32 бита

23 бита

8 битов

Особенностью формата является то, что основание экспоненты равно не 2, а 16. По этой причине три старших бита мантиссы могут быть нулями, и, следовательно, нормализация к старшему биту невозможна.

Такое основание экспоненты "искусственно" увеличивает динамический диапазон представимых чисел за счет (в общем случае) точности.

Описанный формат применяется в таких машинах как 360/37/3081 для представления чисел типа float. Ранее, например, в IBM 7094, использовался похожий 36-битный формат.

Для представления чисел типа double используется дополнительное 32-битовое слово, расширяющее мантиссу до 55 битов.

Формат VAX

Формат

Размер

Мантисса

Экспонента

VAX floating-point

32 бита

23 бита

8 битов

Этот формат используется на некоторых машинах Compaq и DEC. Он идентичен формату, используемому в PDP-11, ставшему основой при разработке [IEEE 754].

В целом, 32-битовый формат VAX повторяет single-формат IEEE с двумя небольшими отличиями. Во-первых, младшие и старшие 16 битов 32-разрядного формата переставлены местами. Во-вторых, представление экспоненты и нормализация числа отличаются так, что в интерпретации IEEE нормализованное число в VAX-формате после перестановки 16-разрядных слов представляет то же IEEE-число, умноженное на 4.

Таким образом, перестановка слов и деление на 4 могут быть ключем к преобразованию формата VAX в single-формат IEEE. В простейшем случае этого будет достаточно.

Формат CRAY

Формат

Размер

Мантисса

Экспонента

CRAY floating-point

64 бита

48 битов

15 битов

Как следует из названия, этот формат применятся на машинах CRAY, таких как X-MP, Y-MP и C-90 (другие модели CRAY основаны на Alpha- и SPARC-процессорах с IEEE-совместимой плавающей арифметикой).

Отличия этого формата от формата IEEE double заключены в ширине мантиссы (48 битов вместо стандартных 53) и экспоненты (15 битов вместо 11) и представлении значения экспоненты (в формате IBM экспонента представляется как целое в форме "знак и модуль", причем взведенный знаковый разряд указывает на ее положительное значение).

Рассылки Subscribe.Ru

:: HDD ::
-обслуживание
-анатомия
-профилактика поломок

Числа с плавающей точкой (floating-point numbers): [C99 5.2.4.2.2, 6.2.5 #10, #11], [C99 Rational 5.2.4.2.2]; модель чисел с плавающей точкой (floating-point model): [C99 5.2.4.2.2], [C99 Rational 5.2.4.2.2]; типы вещественного, комплексного и мнимого доменов (real, complex, and imaginary type domains): [C99 6.2.5 #10, #11, 7.3]; объектное представление (object representation): [C99 6.2.5, 6.2.6], [C++ 3.9]; нормализованные плавающие числа (normalized floating-point numbers): [C99 5.2.4.2.2], [C99 Rational 5.2.4.2.2]; субнормальные плавающие числа (subnormal floating-point numbers): [C99 5.2.4.2.2], [C99 Rational 5.2.4.2.2]; денормализованные плавающие числа (unnormalized floating-point numbers): [C99 5.2.4.2.2], [C99 Rational 5.2.4.2.2]; значения NaN: [C99 5.2.4.2.2], [C99 Rational 5.2.4.2.2]; функции семейства frexp (frexp functions): [C99 7.12.6.4].

[C99] – ISO/IEC 9899:1999, Programming Languages – C

[C99 Rationale] – ISO/IEC Rationale for International Standard – Programming Languages – C, Revision 5.10

[C++] – ISO/IEC 14882:1998, Programming Languages – C++

[IEC 60559] – IEC 60559:1989 – Binary Floating-Point Arithmetic for Microprocessor Systems, Second Edition

[IEEE 754] – ANSI/IEEE 754:1985 – Standard for Binary Floating-Point Arithmetic

[IEEE 854] – ANSI/IEEE 854:1987 – Standard for Radix-Independent Floating-Point Arithmetic

[LIA-1] – ISO/IEC 10967-1 – Standard for Language-Independent Arithmetic

(c) Иван Косарев, 2004. Все права защищены. Публикация и цитирование разрешены только с письменного согласия автора.


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу


В избранное