3.2.4. "Неполноценный" Extended

3.2.4. "Неполноценный" Extended

Ранее мы отметили, что FPU всегда выполняет все операции в формате Extended, оговорившись при этом, что есть исключение из этого правила. Здесь мы рассмотрим это исключение.

У FPU существует специальный двухбайтный регистр, называемый управляющим словом. Установка отдельных битов этого регистра диктует то или иное поведение при выполнении операций. Прежде всего, это связано с тем, какие исключения может возбуждать FPU. Другие биты этого регистра отвечают за то, как будут округляться числа, как FPU понимает бесконечность, — всё это можно при необходимости узнать из документации Intel. Нас же будут интересовать только два бита из этого слова: восьмой и девятый. Именно они определяют, как будут обрабатываться числа внутри сопроцессора.

Если восьмой бит содержит единицу (так установлено по умолчанию), то десять байтов внутренних регистров сопроцессора будут задействованы полностью, и мы получим "полноценный" Extended. Если же этот бит равен нулю, то все определяется значением бита 9. Если он равен единице, то используется только 53 разряда мантиссы (остальные всегда равны нулю). Если же этот бит равен нулю — только 24 разряда мантиссы. Это увеличивает скорость вычислений, но уменьшает точность. Другими словами, точность работы сопроцессора может быть понижена до типа Double или даже Single. Но это касается только мантиссы, экспонента в любом случае будет содержать 15 бит, так что диапазон типа Extended сохраняется в любом случае.

Для работы с управляющим словом сопроцессора в модуле System описана переменная Default8087CW типа Word и процедура Set8087CW(CW: Word). При запуске программы в переменную Default8087CW записывается то управляющее слово, которое установила система при запуске программы. Функция Set8087CW одновременно записывает новое значение в управляющее слово и в переменную Default8087CW.

Такое поведение этой функции не всегда удобно — иногда бывает нужно сохранить старое значение переменной Default8087CW (впрочем, это несложно сделать, заведя дополнительную переменную). С другой стороны, если значение управляющею слова изменить, не используя Set8087CW (а в дальнейшем мы увидим, что такие изменения могут происходить помимо нашей воли), то с помощью функции Default8087CW просто нет возможности узнать текущее значение управляющего слова. В Delphi 6 и выше появилась функция Get8087CW, позволяющая узнать значение именно контрольного слова, а не переменной Default8087CW. В более ранних версиях существовал единственный способ получить значение этого слова — встроенный в Delphi ассемблер.

Итак, установить значение управляющего слова можно с помощью команды FLDCW, прочитать с помощью FNSTCW. Обе эти команды имеют один аргумент — переменную типа Word. Чтобы, например, установить 53-значную точность, не изменив при этом другие биты управляющего слова нужно выполнить такую последовательность команд:

asm

 FNSTCW MyCW

 AND MyCW, 0FC00h

 OR MyCW, 200h

 FLDCW MyCW

end;

Начиная с Delphi 6, в модуле Math появилась еще одна функция, позволяющая устанавливать точность FPU без манипуляции с отдельными битами управляющего слова — SetPrecisionMode. В зависимости от значения аргумента (pmSingle, pmDouble или pmExtended) она устанавливает требуемую точность. Современные сопроцессоры обрабатывают числа с такой скоростью, что при обычных вычислениях вряд ли может возникнуть необходимость в ускорении за счет точности — выигрыш будет ничтожен. Эта возможность необходима, в основном, в тех случаях, когда вычисления с плавающей точкой составляют значительную часть программы, а высокая точность не имеет принципиального значения (например, в 3D-играх). Однако забывать об этой особенности работы сопроцессора не следует, потому что она может преподнести один неприятный сюрприз, о котором чуть позже.

Данный текст является ознакомительным фрагментом.