Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 [ 78 ] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261

4.2. АРИФМЕТИКА ЧИСЕЛ С ПЛАВАЮЩЕЙ ТОЧКОЙ

В этом РАЗДЕЛЕ рассмотрены основные принципы выполнения арифметических операций над числами с "плавающей точкой" и проанализирован внутренний механизм таких вычислений. Вероятно, у многих читателей данная тема не вызовет слишком большого интереса либо потому, что в вычислительных машинах, на которых они работают, имеются встроенные команды операций над числами с плавающей точкой, либо потому, что нужные подпрограммы содержатся в операционной системе. Но не следует считать, что материал этого раздела относится исключительно к компетенции инженеров - конструкторов ЭВМ или узкого круга лиц, которые пишут системные подпрограммы для новых машин. Каждый грамотный программист должен иметь представление о том, что происходит при выполнении элементарных шагов арифметических операций над числами с плавающей точкой. Предмет этот совсем не так тривиален, как принято считать; в нем удивительно много интересного.

4.2.1. Вычисления с однократной точностью

А. Обозначение чисел с плавающей точкой. В разделе 4.1 были рассмотрены различные способы обозначения чисел с фиксированной точкой. При таком способе обозначения программист знает, где положено находиться разделяющей точке в числах, с которыми выполняются те или иные операции. В некоторых ситуациях при выполнении программы значительно удобнее сделать положение разделяющей точки динамически изменяющимся, иными словами, сделать точку "плавающей" и связать с каждым числом информацию о ее положении. Эта идея уже давно использовалась в научных расчетах, в особенности для представления очень больших чисел наподобие числа Авогадро = 6.02214 х 10 или таких очень малых чисел, как постоянная Планка h = 6.6261 х 10~ эрг-с.

В этом разделе речь пойдет о р-разрядных числах с плавающей точкой по основанию b с избытком q. Такое число представляется парой величин (е,/), которой отвечает значение

(е,/)=/хЬ«-«. (1)

Здесь е - целое число, изменяющееся в соответствующем интервале значений, а / - дробное число со знаком. Условимся, что

1/1 < 1,

иными словами, разделяющая точка в позиционном представлении / находится в крайней слева позиции. Точнее говоря, соглашение о том, что мы имеем дело с р-разрядными числами, означает, что bf - целое число и

-Ь" < bPf < b". (2)

Термин "двоичное число с плавающей точкой", как всегда, будет означать, что 6 = 2, термин "десятичное число с плавающей точкой" - что 6 = 10 и т. д. Используя 8-разрядные десятичные числа с плавающей точкой с избытком 50, можно, например, написать

число Авогадро = (74, -I-.60221400);

постоянная Планка Л = (24,-I-.66261000).



Две компоненты, ей/, числа с плавающей точкой называются его порядком и дробной частью соответственно. (Иногда используются и другие названия, особенно "характеристика" и "мантисса"; однако слово "мантисса" для обозначения дробной части приводит к путанице в терминологии, так как этот термин употребляется совсем в другом смысле в теории логарифмов и, кроме того, английское слово "mantissa" означает "мало дающее добавление".)

В компьютере MIX числа с плавающей точкой имеют вид

±

Это представление с плавающей точкой по основанию Ь с избытком q, с четырьмя значащими "цифрами", где Ь есть размер байта (т. е. 6 = 64 или Ь - 100) и q равняется \\Ь\. Дробная часть равна ± , а порядок и е находится в интервале О < е < Ь. Такое внутреннее представление - типичный пример соглашений, которые приняты в большинстве существующих компьютеров, хотя основание Ь здесь гораздо больше, чем обычно используемое.

В. Нормализованные вычисления. Число с плавающей точкой (е,/) является нормализованным, либо если наиболее значимая цифра в представлении / отлична от нуля, так что

1/Ь < 1/1 < 1, (5)

либо если / = О, а е принимает наименьшее возможное значение. Чтобы установить, какое из двух нор.мализованных чисел с плавающей точкой имеет большую величину, достаточно сравнить их порядки; только если порядки равны, нужно анализировать и дробные части.

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

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

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



Al. Распаковать

Обеспечить выполнение условия ви > Bv

Установить ей

ей >ev


Проверить Си - ву

1 N.

Масштабировать, сдвинув вправо

1 ?

Сложить

Нормализовать

>

Рис. 2. Сложение чисел с плавающей точкой.

Первый (и наиболее трудный!) из алгоритмов, обсуждаемых в этом разделе,- это процедура сложения чисел с плавающей точкой:

(е„,/„) © (е„,Л) = (е„,/„).

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

©, е, ®, 0,

чтобы отличать приближенные операции от точных.

Идея, лежащая в основе сложения с плавающей точкой, довольно проста. Полагая, что е„ > е„, формируем результат по принципу = е„, fw = fu + Л/6"~" (таким образом, выравнивается положение разделяющих точек и соответственно положение разрядов слагаемых), а затем нормализуем результат. Может возникнуть несколько ситуаций, которые делают выполнение этого процесса нетривиальным; более- точное описание метода дается в следующем алгоритме.

Алгоритм А {Сложение чисел с плавающей точкой). Для заданных р-разрядных нормализованных чисел с плавающей точкой и = {eu,fu) и v = (ev,fv) по основанию Ь с избытком q строится сумма tv = u®v. Данный алгоритм (рис. 2) можно использовать и для вычитания чисел с плавающей точкой, если v заменить на -v.

Al. [Распаковать.] Выделить порядок и дробную часть в представлениях для и и v.



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 [ 78 ] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261