AOP_Tom2 (1021737), страница 69
Текст из файла (страница 69)
Для того чтобы выполнить необходимые корректирующие операции после обнаружения исчезновения нли переполнения, нужно заранее позаботиться о сохранении достаточной для этого информации. Отладка подпрограмм выполнения арифметцческих операций над числами с плавающей точкой — обычно довольно сложная задача из-за обилия различных случаев, которые нужно предусмотреть.
Ниже перечислены распространенные ловушки, подстерегающие программиста, который занимается программами "плавающей аРифметики". К сожалению, некоторые программисты во многих случаях пренебрегают исчезновением порядка. Они просто полагают, что исчезающе малые результаты равны нулю без индикации ошибки. Часто зто приводит к серьезной потере точности (а на самом деле к потере всех значащих цифр), что нарушает соглашения, принятые в операциях над числами с плавающей точкой. Таким образом, системная подпрограмма действительно должна информировать прикладного программиста об исчезновении порядка. Приравнивание результата к нулю допустимо только в отдельных случаях, когда результат должен складываться со значительно большей величиной.
Если исчезновение порядка не фиксируется, то возникают таинственные ситуации, когда (и З р) З ш равно нулю, а и З (с З и) нет, поскольку, скажем, умножение и Зп приводит к исчезновению порядка, а иЗ(сЗш) вычисляется и без выхода порядков за пределы допустимого интервапа. Подобным же образом можно найти пять таких положительных чисел а, Ь, с, и и у, что (а Зу Ю Ь) З (сЗу гп с1) (а 61 ЬЗу)З(с 61 дЗу) = 1, если исчезновение порядка не фиксируется (см.
упр. 9). Даже с учетом того, что подпрограммы арифметики с плавающей точкой не идеально точны, такие несуразные результаты, как (11), совсем уж неожиданны для случая, когда все числа а, Ь, с, д и у положительны! Исчезновение порядка обычно не предугалывается программистом, так что ему следует об этом сообщать*. 3) Попадание "мусора". При выполнении сдвига влево необходимо проследить, чтобы в освобождающиеся разряды справа не было введено чего-либо, отличного от нулей. Например, обратите внимание на команду ЕУТХ О в строке 21 программы А и "слишком легко забываемую" команду ЕУТХ О в строке 04 подпрограммы РЬОТ в (10). (Но было бы ошибкой очищать регистр Х после строки 27 в подпрограмме деления.) 4) Непредусмотренное переполнение при округлении. Когда число наподобие .999999997 округляется до В цифр, происходит перенос влево от десятичной точки и результат сдвигается вправо. Многие ошибочно считали, что в ходе выполнения С другой стороны, нужно отметить, что современные языки программирования высокого уровня предоставляют программисту (или вовсе не предоставляют) весьма огреинчеиные возможности использования информации, содержащейся в стандартных программах арифметики с плввэющей точкой.
Подпрограммы для КХХ, которые представлены в этом разделе, проста остенввливвют Работу, обиеружив такую ситуацию, в эта отнюдь не выход. Существует множество приложений, дяя которых исчезновение порядка относительна безвредна, и потомч желательно ивйти способ, пользуясь которым прогрвмлгист смог бы просто н безопесио для приложения справиться с возникшей проблемой. Практика подстеновки "втихомолку" нуля вместо результата с исчезнувшим порядком себя полностью дискредитировала, но существует альтернатива, которая в последнее время звваевывэет все большую популярность. Ее суть в том, чтобы модифицировать самое определение формата представления чисел с пввввющей точкой, допуская существоввние ненормализоввиной дробной части в случве, если порядок имеет минимальное допустимое значение.
Зтв идея "постепенной потери знечимости" впервые была ревлизаввив в компьютере Е1естго!ай1се Хб; онв лишь незнвчительио усложниле алгоритмы выполнения операций, на совершенно исключила возможность исчезновения порядка при сложении и вычитвиии, Рассмотрение этой иден вмхадит зв рамки данной книги, поэтому в простых формулех внзлизв относительной ошибки вычислений в разделе 4.2.2 появление постепенной потери значимости не учитывается. Тем ие менее, используя формулы, подобные гоппб(х) = х(1 — б) -~- с, где ~б, '< Ь' г(2 и ~с) < Ь ™72, можно поквзвтзч чта формат с постепенной потерей энвчимости успешно срабатывает ва многих важных случаях.
(См. %. М. Квьвп епб Л. Рв1шег, АСМ ЯСЬ ПЛ! Мепз!еыег (Оссоьег, 1979), 13-21.) умножения переполнение прн округлении невозможно, так как максимальное значение )7'„~е) равно 1 — 26 "+ 6 ге, а это число не может округлиться до 1. Ошибочность такого рассуждения продемонстрирована в упр. 11.
Любопытно, что переполнение при округлении действительно невозможно при делении чисел с плавающей точкой (см. упр, 12). Су.ществует направление, представители которого утверждают, что можно безболезненно "округлять" .999999997 до .99999999, а не до 1.0000000, поскольку последний результат представляет все числа из интервала (1.0000000 — 5 х 10 г ..
1.0000000 + 5 х 10 ~), в то время как .99999999 представляет все числа из гораздо меньшего интервала (.99999999 — 5 х 10 э ...99999999 + 5 х 10 э). Хотя второй интервал и не содержит исходного числа .999999997, каждое число из второго интервала содержится в первом, так что последующие вычисления со вторым интервалом не менее точны, чем с первым. Но этот довод несовместим с математической идеологией арифметики с плавающей точкой, представленной ниже, в разделе 4.2.2.
5) Округление до нормализации. Неточность результата порождается и преждевременным округлением в неверных цифровых разрядах. Эта ошибка очевидна, когда округление производится слева от соответствующего разряда. Она также опасна в менее очевидном случае, когда округление сначала выполняется намного правее, а затем — в истинном разряде. По этой причине ошибочно осуществлять округление в ходе операции "сдвиг вправо" на шаге А5; исключением является случай, рассмотренный в упр. 5. (Однако специальный случай округления на шаге э5, а затем повторного округления уже после переполнения при округлении безобиден, потому что переполнение при округлении всегда приводит к значению ~1.0000000, которое не меняется в результате последующей процедуры округления.) 6) Невозможность сохранения достаточной точности в промежуточных вычислениях.
Детальный анализ точности арифметических операций с плааа|ощей точкой, проводимый в следующем разделе, показывает, .что нормализующне программы арифметики с плавающей точкой должны всегда обеспечивать максимальную точность подходящим образом округленного результата. Не должно быть никаких отступлений от этого принципа, даже в тех случаях, появление которых предельно маловероятно. Надлежащее число значащих цифр следует сохранять в ходе всех промежуточных вычислений, как реализовано в алгоритмах А и М. С. Аппаратная реализация арифметических действий над числами с плавающей точкой. В арсенале почти каждой большой ЭВМ, предназначенной для научных расчетов, содержатся встроенные операции и команды арифметических операций над числами с плавающей точкой.
К несчастью, в аппаратных реализациях таких команд обычно присутствуют некоторые дефекты, приводящие при определенных обстоятельствах к удручающе скверному поведению машины, и, надо надеяться, в будущем создатели вычислительной техники будут уделять больше внимания данному вопросу. Затраты на это очень малы, н соображения, представленные в следующем разделе, показывают, какой выигрыш может быть достигнут. Из того, что сегодня известно, следует, что для современных компьютеров не подходят вчерашние компромиссные решения.
Компьютер М1Х, используемый в этой серии книг как пример "типичной" вычислительной машины, оснащается средством расширения для работы с числами в формате с плавающей точкой — арифметическим расширителем. Он доступен за небольшую дополнительную сумму и обеспечивает выполнение следующих шести команд на аппаратном уровне. ° РАПП, ГНОЯ, ГМ01., ГПТЧ, ГЕОТ, ГСМР (С = 1, 2, 3, 4, 5, 56 соответственно; Р = 6).
Содержимое регистра гА после выполнения команды РАПП Ч такое же, как и содержимое гА после выполнения команд БТА АСС; ЕПА Ч; ЗМР РАПП. Здесь РАПП вЂ” подпрограмма, которая уже появлялась выше в этом разделе, но оба операнда автоматически нормализуются непосредственно перед входом в подпрограмму, если они еще не были нормализованы. (Если во время предварительной нормализации, но не во время нормализации результата, возникает исчезновение порядка, вызывающая программа о нем не извещается,) Аналогичные замечания относятся к операциям ГБПВ, ГМ01 и Г01Ч.
Содержимое регистра гА после выполнения операции ГЕОТ совпадает с его же содержимым после выполнения команды 1МР ГЕОТ в подпрограмме (10). Содержимое гА не искажается командой ГСМР Ч. Эта команда устанавливает индикатор сравнения в состояние ПЕЯБ, ЕЦОАП или ОЕЕАТЕН в зависимости от того, будет ли содержимое гА "заметно меньше, чем", "примерно равно" или "заметно больше, чем" Ч, как обсуждается в следующем разделе. Работа этой команды в точности моделируется подпрограммой ГСМР из упр.
4.2.2-17 с ЕРЯХЕОМ в ячейке О. Ни одна из команд арифметики с плавающей точкой не воздействует ни на какой другой регистр, помимо гА. Если происходит переполнение или исчезновение порядка, то включается индикатор переполнения и указывается порядок результата по модулю размера байта. Попытка деления на куль оставляет в регистре гА "мусор" (произвольное значение).
Времена выполнения: 4и, 4и, 9и, 11и, Зи и 4и соответственно. ° Г1Х (С = 5; Р = 7). Содержимое гА заменяется целым числом "гоцпб(гА)", округленным до ближайшего целого, как на шаге 1ЧЯ алгоритма Х. Однако, если этот результат слишком велик и не вмещаетси в разрядную сетку регистра, устанавливается индикатор переполнения и результат должен трактоваться как неопределенный. Время выполнения: Зи. Иногда полезно использовать операторы арифметики с плавающей точкой нестандартным образом. Например, если бы операция ГЕОТ не была реализована как часть арифметического расширителя компьютера М1Х, можно было бы легко обеспечить ее выполнение для 4-байтовых чисел, написав маленькую подпрограмму ГЕОТ БТЗ 9Г ЯЕА 1 ЕМТХ 0+4 (12) ЯНС 1 РАПП =0= 9Н ЗМР Эта программа не эквивалентна команде ГЕОТ, так как в ней предполагается, что 1:1 байт регистра гА равен нулю; кроме того, она портит содержимое регистра гХ.
В более общих ситуациях приходится прибегать ко всяким хитростям, потому что переполнение при округлении может происходить даже во время выполнения команды РВОТ. Аналогично предположим, что И1Х имеет команду РА00, но не имеет Р1Х. Чтобы округлить число и, записанное в формате с плавающей точкой, до ближайшего целого числа с фиксированной точкой (прнчем известно, что число неотрицательно и займет не более трех байтов), в программе можно записать РА00 Р00СЕ, где в нчейке Р000Е содержится константа результат в гА будет иметь вид (13) П. История и библиография. Истоки арифметики чисел с плавающей точкой прослеживаются вплоть до вавилонян (около 1800 г.