Режим компиляции $N+ является глобальным и не может меняться в дальнейшем. При создании модулей (UNIT), ориентированных на работу с сопроцессором, т.е. использующих вводимые им типы, указание ключа $N+ в них необязательно. Важно лишь, чтобы он был в главной программе, включающей в себя эти модули.
При необходимости отключить сопроцессор должен указываться ключ $N-. При этом программа может перестать компилироваться (компилятор «забудет» типы чисел с повышенной точностью).
Если в ПЭВМ установлен сопроцессор, то компилятор сам определяет ключевое слово CPU87 для условной компиляции. Это можно использовать для автоматического выбора режима компиляции:
{$IFDEF CPU87} {$N+} {$ELSE} {$N-} {$ENDIF}
Приведенная выше конструкция определяет, как будет скомпилирован текст — в расчете на сопроцессор или без него.
После компиляции выполнение программы всякий раз начинается с проверки наличия сопроцессора и определения его типа. Результат проверки записывается в предопределенную переменную системной библиотеки — Test8087 типа Byte (табл. 9.8).
Таблица 9.8
Значения Test8087 | Расшифровка |
0 | Сопроцессор не обнаружен |
1 | Подключен 8087 |
2 | Подключен 80287 |
3 | Подключен 80387 |
Если программа компилировалась в режиме {$N+}, а значение Test8087 получилось равным 0, то программа остановится с выдачей сообщения о необходимости сопроцессора. Существует, однако, средство отключить автоматическую проверку наличия сопроцессора при запуске программы. Надо ввести системную переменную MS-DOS с именем 87 и значениями Y (от YES — да) и N (от NO — нет). Лучше всего это сделать в файле AUTOEXEC.BAT, вставив строку
- 182 -
SET 87=Y (или N)
Значение системной переменной MS-DOS 87, равное Y, прикажет считать сопроцессор подключенным, а N — соответственно отключенным. Вообще говоря, лучше не обманывать технику и программы. Приберегите эту методику (с SET 87=) на самый крайний случай.
Турбо Паскаль дает возможность эмулировать работу сопроцессора программным путем. Это означает, что можно создать программу, которая будет работать с высокой точностью независимо от наличия сопроцессора. Обнаружен сопроцессор — хорошо, он и будет нагружен, нет сопроцессора — вся точность будет получена имитацией его. Понятно, что в последнем случае будут потери во времени счета, и немалые. Включением эмуляции управляет ключ $Е. Он имеет смысл только рядом с ключом $N. Возможны такие их сочетания:
{$N+, E+} — подключение библиотеки для эмуляции сопроцессора; при его отсутствии точность обеспечивается программно за счет скорости; {$N+, E-} — программа сможет работать только на машинах с сопроцессором;
{$N-,E+} и {$N-,E-} — сопроцессор не используется, ключ эмуляции игнорируется. Программа работает только с обычной точностью и скоростью.
Если в программу вставлен внешний код директивой {$L Имя-Файла.OBJ}, то для работы с сопроцессором этот код должен быть получен с учетом использования инструкций 80X87.
Преимущества от использования сопроцессора — это, в первую очередь, скорость вычислений, которая может вырасти в несколько раз. Второе преимущество — увеличение точности вычислений с плавающей точкой. В расчете на математический сопроцессор вводятся типы, приведенные в табл. 9.9.
Таблица 9.9
Тип | Диапазон значений | Количество значащих цифр | Размер в байтах |
Single | 1.5E-45..3.4e+38 | 7-8 | 4 |
Double | 5.0E-324..1.7E+308 | 15-16 | 8 |
Extended | 3.4E-4932..1.1E+4932 | 19-20 | 10 |
Comp | -9.2E+18..9.2E+18 | 19-20 | 8 |
Все эти типы — вещественные, за исключением Comp, который является «очень длинным» целым типом (хранит только целые
- 183 -
значения). Диапазон этого типа в таблице задан округленно, так как реальные числа (от -2 до 263-1) слишком длинны.
Обычный тип Real (6 байт, диапазон 2.9Е-39...1.7Е+38, 11-12 значащих цифр) будет работать с сопроцессором, но крайне неэффективно. Этот формат — чужой для сопроцессора, и время, «съедаемое» преобразованием его в сопроцессорный тип, перекрывает ускорение. А точности не добавляется. Поэтому лучше всего ввести свой тип, например Float, и понимать под ним либо Real, либо чисто сопроцессорный вещественный тип в зависимости от режима компиляции.
{$N... <-- какой-либо режим }
{$IFOPT N+}
TYPE
Float = Double; { или любой другой тип для 80X87 }
{$ELSE>
TYPE
Float = Real; { без 80X87 — только этот тип }
{SENDIF}
VAR { переменные типа Float }
r : Float;
d : Array [1..9] of Float;
Целые типы Турбо Паскаля работают с сопроцессором без каких-либо оговорок.