необходимо выполнить следующие операции:
A. F2XM1 вычисляет 2(X) - 1
B. FLDL2T константа log 10 по основанию 2
C. FLDL2E константа log E по основанию 2
D. FYL2X вычисляет Y * log X по основанию 2
E. FLDLG2 константа log 2
F. FLDLN2 константа log 2 по основанию E
Мы знаем, что как только загружается целое число, мы должны
или умножить его на степень десяти для числа с положительной экс-
понентой по основанию десять, или разделить его на степень десяти
для числа с отрицательной экспонентой по основанию десять. Из
правила 1 видно, что первым шагом к получению степени числа 10
является возведение числа 2 в некоторую степень Х.
Вычисление 2
Обычно, число 2 может быть возведено в степень посредством
простого сдвига, как раз то, что делает NPX своей командой
FSCALE. К сожалению, это не является полным решением, так как це-
лые степени числа 10 не соответствуют целым степеням числа 2. Не-
обходимо вычислить некоторую дробную часть числа 2. Для этого
служит команда NPX F2XM1 (смотрите правило А).
Команда F2XM1 может возводить 2 в степень Х, где значение Х
лежит в диапазоне от 0.0 до 0.5 включительно. Взяв произвольное
число Х, мы можем разбить его на целую и дробную части, вычислив
следующие выражения:
- 10-36 -
целая (Х) = FRNDINT(X)
дробная(Х) = FSUB X - целая(Х)
Целая часть Х используется в FSCALE для возведения числа 2 в
целую степень, а дробная часть применяется командой F2XM1. Мы мо-
жем использовать две последовательные операции, так как знаем,
что для любых значений Y и Z справедливо следующее равенство:
2(Y+Z) = 2(Y) * 2(Z)
Абсолютное значение дробной части Х находится в пределах от
0.0 до 0.5, с учетом того, что управление округлением NPX уста-
новлено в режим округления к ближайшему, что обеспечивает макси-
мальную дробную часть, равную 0.5.
Затем мы можем вычислить весь результат, применив F2XM1, при-
бавив 1 обратно к результату, и использовав FSCALE. Конечно, если
дробная часть отрицательная, мы должны удостовериться, что приме-
няем ее абсолютное значение и для получения правильного результа-
та использовать равенство
2(Y-Z) = 2(Y)/2(Z)
Это последовательность событий имеет место в программе EXP2, на-
ходящаяся ближе к концу следующего листинга (Листинг 10-2).
Вычисление 10
Теперь, определив, как вычислять 2 в степени Х, мы выполнили
главную часть вычисления 10 в степени Х. Из правила 1 мы знаем,
что
10(X) = 2(X) * log 10 по основанию 2,
значит нам нужно найти значение
X * log 10 по основанию 2
в целях использования только что разработанной программы возведе-
ния числа 2 в степень Х. Из правила B видно, что NPX может дать
нам значение логарифма 10 по основанию 2. Вычисление 10 в степени
Х выполняется операцией FLDL2T, с последующим умножением FMUL и
завершается вызовом EXP2. Эти команды имеются в программе EXP10,
содержащейся в листинге 10-2.
Изменяя тождества логарифм 10 по основанию 2 на логарифм e по
основанию 2 и логарифм Х по основанию 2, мы можем вычислить с по-
мощью программы EXP2 значения 10 в степени Х, e в степени Х и Y в
степени Х.
Функция масштабирования десятичного в вещественное
Что нам делать с полученным значением 10 в степени Х? Нам не-
обходимо это число для использования экспоненциального формата.
Имея число в формате упакованного BCD и целое слово Х для экспо-
ненты, мы можем преобразовать части в вещественное число с плава-
- 10-37 -
ющей запятой посредством загрузки значащей части упакованного BCD
с помощью FBLD. Мы вычисляем 10 в степени абсолютного значения Х
и затем либо умножаем результат на мантиссу для положительного Х
(FMUL), либо делим мантиссу на результат от возведения 10 в сте-
пень Х для отрицательных экспонент (FDIV). Это, как Вы, возможно,
уже поняли, делает программа DEC2FLT, представленная в листинге
10-2. Программа выглядит длиннее, так как нам необходимо следить
и устанавливать знак экспоненты.
Используя пакет программ EXP2, EXP10 и DEC2FLT, можно полу-
чить число, состоящее из двух частей (мантисса в виде упакованно-
го BCD и целая экспонента), которое главный центральный процессор
генерирует и превращает в вещественное число с плавающей запятой
внутри NPX.
Функция масштабирования вещественного в десятичное
Введя числа в NPX, мы можем производить вычисления над ними.
Если мы выходим из комнаты, то можем сохранить их в общей памяти
как временные вещественные (это делает команда FSTP). Но что де-
лать, когда надо взглянуть на результаты? Что надо сделать для
того, чтобы преобразовать вещественное число с плавающей запятой
в целое число, состоящее из двух частей?
Ответ заключается в том, что мы должны поработать со смещен-
ной экспонентой NPX таким образом, чтобы NPX выдало нам целую
мантиссу. При сохранении числа как строки упакованного BCD коман-
да FBSTP сначала округляет число к ближайшему целому. Если число
слишком велико для представления строкой упакованного BCD, NPX не
может сохранить это число. Если число слишком мало, то точность
мантиссы при округлении числа теряется. Для того, чтобы применить
команду FBSTP, мы должны сначала убедиться в том, что число, хра-
нящееся в регистре, лежит в соответствующем диапазоне.
Мы можем сказать, что число лежит в соответствующем диапазо-
не, так как его смещенная экспонента (двоичная десятичная запя-
тая) имеет значение меньше, чем 64 (в противном случае число
слишком велико) и больше, чем количество двоичных цифр мантиссы
(в противном случае мы теряем точность). Обычно мы выбираем чис-
ло, которое нам даст хорошую точность. Для числа, которое мы хо-
тим иметь с точность до 10 десятичных цифр, значение экспоненты
32 является хорошим значением. Это означает, что двоичная деся-
тичная запятая находится в бите 32, примерно на половине пути до
конца плавающей запятой. Не слишком большое и не слишком малень-
кое.
Как быть, если число имеет экспоненту, не лежащую в этом диа-
пазоне? Мы должны поменять экспоненту. Первым шагом является оп-
ределение того, какую экспоненту надо реально использовать. Мы
применяем команду FXTRACT, которая разбивает регистр данных NPX
на два, один из которых содержит мантиссу с нулевой экспонентой
(ST), а другой содержит правильную экспоненту первоначального
числа как вещественное число (ST(1)). Мы интересуемся регистром
ST(1).
Первым шагом вычисления является определение того, сколько
двоичных десятичных мест мы убрали. Иными словами, мы хотим опре-
делить расстояние между желаемой и существующей экспонентой. Ко-
манда FSUB может сказать нам это очень быстро.
Зная расстояние, можем ли мы использовать его в качестве ко-
эффициента масштабирования (с помощью FSCALE) для первоначальной
- 10-38 -
экспоненты? Нет, потому что при отображении числа в экспоненци-
альном формате нам надо показать пользователю экспоненту в виде
+ 1.2345600000Е + 00,
а мы не можем это сделать, если экспонента является степенью чис-
ла 2. Идея этого упражнения заключается в том, чтобы NPX выдало
целое число и затем узнать, на сколько степеней числа 10 это чис-
ло было сдвинуто для получения целого. Привести в порядок экспо-
ненциальный формат.
Нам нужно каким-то образом преобразовать расстояние, которое
в настоящее время выражает степень числа 2, в расстояние целых
степеней числа 10. Оказывается, взаимоотношение между двумя зна-
чениями выражается следующим правилом:
2(X) = 10(X * log 2)
2(X) = 10(X * log 10 по основанию 2)
Второе взаимоотношение является результатом тождества:
log b по основанию a = 1/log a по основанию b
Не смотря на то, какой способ мы использовали, мы определили
значение Х (для выражения 10 в степени Х), требуемое для создания
соответствующего коэффициента масштабирования. Мы можем создать
коэффициент, применяя команды FLDLG2 (логарифм числа 2 по основа-
нию 10) и FMUL, или команды FLDL2T (логарифм числа 10 по основа-
нию 2) FDIV. Тем не менее, эти методы дают точное значение Х для
числа 10 в степени Х и нам необходимо ближайшее целое. Поэтому мы
применим команду FRNDINT для округления числа и получим нашу экс-
поненту по основанию 10.
Имея экспоненту, мы возводим 10 в степень Х (с помощью коман-
ды EXP10) и получаем коэффициент масштабирования для перевода ве-
щественного числа в целое (с помощью FMUL). Экспонента 10 возвра-
щается командой FIST (сохранить целое) и мантиссу командой FBSTP
(сохранить упакованный BCD). Все, за исключением сохранения BCD,
содержится в программе FLT2DEC, представленной в листинге 10-2.
Другой полезной хитростью является то, что однажды записав в
память число в формате упакованного BCD, мы можем использовать
программу отображения двоичного кода в шестнадцатиричном (напри-
мер, BIN2HEX) для вывода на экран цифр, потому что они очень по-
хожи на шестнадцатиричное число.
Мы говорили о листинге 10-2, и вот, наконец, подошла его оче-
редь. Обратите внимание, что как и в программе DUMP87, она также
сформатирована для использования в качестве библиотеки. Кроме то-
го, все операции выполняются в стеке главного центрального про-
цессора или в ячейках, определенных вызывающим оператором, поэто-
му проблем с переносимостью не возникнет.
Листинг 10-2. DE2FLT, FLT2DEC и программы экспоненты
EXP2, EXP10, EXPE и EXRY
______________________________________________________________
PAGE 60,132 ; широкий листинг
#.8087 ; разрешить трансляцию команд 8087 NPX
;
PUBLIC dec2flt ; определить библиотечную программу
PUBLIC flt2dec ; определить библиотечную программу
- 10-39 -
PUBLIC exp10 ; определить библиотечную программу
PUBLIC expE ; определить библиотечную программу
PUBLIC expY ; определить библиотечную программу
PUBLIC exp2 ; определить библиотечную программу