Глава 23
Фиксированная точка,
плавающая точка
В обыденной жизни мы свободно переходим от целых чисел к
дробям и процентам. Мы покупаем пол-упаковки яиц, кассир
прибавляет к их цене налог 8 1/4 %, и мы расплачиваемся день-
гами, полученными за 2 3/4 часа сверхурочной работы по та-
рифу в 1,5 раза больше обычного. Подобными числами боль-
шинство людей оперирует вполне уверенно, хотя и не всегда
умело. Мы даже спокойно воспринимаем слова статистиков
«средняя американская семья состоит из 2,6 человека» и не со-
дрогаемся при мысли о том, какое ужасное и повсеместное
членовредительство к этому привело.
К сожалению, в компьютерной памяти целые числа и дро-
би не соседствуют с той же легкостью. Да, в компьютерах все
закодировано битами, т. е. в виде двоичных чисел. Но некото-
рые числа выразить битами легче, чем другие.
Свое знакомство с битами мы начали с того, что представ-
ляли с их помощью числа, которые на языке математики на-
зываются положительными натуральными или положитель-
ными целыми. Мы также убедились, что для представления
целых отрицательных чисел удобно применять дополнения до
двух, поскольку это облегчает сложение положительных и от-
рицательных чисел. В таблице показано, какие целые числа без
знака (положительные) и со знаком (отрицательные в виде
424
Глава двадцать третья
дополнения до двух) можно хранить в 8-, 16- и 32-разрядных
ячейках памяти.
Число
Диапазон целых
Диапазон целых
битов
положительных чисел
отрицательных чисел
8
От 0 до 255
От –128 до 127
16
От 0 до 65 535
От –32 768 до 32 767
32
От 0 до 4 294 967 295
От –2 147 483 648
до 2 147 483 647
На этом мы и остановились. Но, помимо целых, в матема-
тике есть также рациональные числа, которые можно предста-
вить в виде дроби, т. е. отношения двух целых чисел. Напри-
мер, 3/4 — рациональное число, так как оно является отноше-
нием 3 и 4. В форме десятичной дроби это же число записыва-
ется так: 0,75. Несмотря на иную форму записи, это тоже ра-
циональное число, равное отношению 75 и 100.
В десятичной системе счисления слева от десятичного раз-
делителя стоят цифры-множители целых положительных сте-
пеней десяти. Цифры справа от десятичного разделителя яв-
ляются множителями отрицательных степеней десяти. Скажем,
число 42 705,684 можно записать так:
4
´ 10 000 +
2
´ 1000 +
7
´ 100 +
0
´ 10 +
5
´ 1 +
6
¸ 10 +
8
¸ 100 +
4
¸ 1000
Здесь я использовал знаки деления, но можно обойтись и без
них — с помощью десятичных дробей:
4
´ 10 000 +
2
´ 1000 +
7
´ 100 +
0
´ 10 +
5
´ 1 +
6
´ 0,1 +
8
´ 0,01 +
4
´ 0,001
425
Фиксированная точка, плавающая точка
или степеней десяти:
4
´ 10
4
+
2
´ 10
3
+
7
´ 10
2
+
0
´ 10
1
+
5
´ 10
0
+
6
´ 10
–1
+
8
´ 10
–2
+
4
´ 10
–3
Некоторые рациональные числа не так-то легко предста-
вить в виде десятичной дроби. Самый простой пример — 1/3.
Разделив 1 на 3, получим:
0,3333333333333333333333333333333333333...
и так без конца. Нужно признать, что в форме десятичной дро-
би число 1/3 выглядит несколько неуклюже, и все же это пол-
ноценное рациональное число, являющееся отношением двух
целых чисел. Существуют и более сложные периодические
десятичные дроби, например, 1/7:
0,142857142857142857142857142857142857142857...
Числа, которые нельзя представить в виде отношения це-
лых чисел, называются иррациональными. Они записываются
в виде бесконечных десятичных дробей без каких бы то ни
было повторений. Примером может служить квадратный ко-
рень из 2 — решение алгебраического уравнения х
2
– 2 = 0:
2~
~1.4142135623730950488016887242096980785696718...
Иррациональное число, которое не является решением ал-
гебраического уравнения с целочисленными коэффициента-
ми, называется трансцендентным. Все трансцендентные чис-
ла иррациональны, но не все иррациональные числа трансцен-
дентны. К трансцендентным числам относится знаменитое
число
p, равное отношению длины окружности к ее диаметру:
3,14159265358979328462643383279502884...
Другое трансцендентное число — е, к которому стремится зна-
чение выражения:
426
Глава двадцать третья
1 +
n
1
n
при n, стремящемся к бесконечности. Оно приблизительно
равно:
2,718281828459045235360287471352662497757247...
Вместе рациональные и иррациональные числа называют-
ся действительными или вещественными числами. Противо-
положность им — мнимые числа: квадратные корни из отри-
цательных величин. Комплексные числа являются комбинаци-
ей реальных и мнимых чисел. Несмотря на подозрительное
название, мнимые числа существуют и даже активно исполь-
зуются в решении многих научных и практических задач.
Мы привыкли думать о непрерывном ряде чисел. Дайте мне
два рациональных числа, и я всегда найду между ними третье,
например, их среднее арифметическое. Но цифровые компью-
теры не имеют дела с непрерывностью. Бит равен либо 0, либо
1 и никаких промежуточных значений не допускает. По самой
своей сути компьютеры обречены работать с дискретными ве-
личинами. Количество таких величин, представимых с помо-
щью битов, напрямую зависит от количества последних. Так, в
32-битовой ячейке памяти можно хранить положительные це-
лые числа от 0 до 4 294 967 295. Чтобы записать в память компь-
ютера значение 4,5, нужно придумать что-то другое.
Можно ли представить в двоичном виде дробные величи-
ны? Можно. Самый простой способ — прибегнуть к двоично-
десятичному коду (ВСD), о котором мы говорили в главе 19.
Код ВСD предназначен для записи в двоичной системе деся-
тичных чисел. Каждой десятичной цифре (0, 1, 2, 3, 4, 5, 6, 7, 8
и 9) сопоставлено 4-битовое двоичное число:
Десятичная цифра
Двоичная число
0
0000
1
0001
2
0010
3
0011
4
0100
427
Фиксированная точка, плавающая точка
5
0101
6
0110
7
0111
8
1000
9
1001
Код ВСD, в частности, удобно применять в компьютерных про-
граммах, работающих с денежными суммами, когда в дроб-
ных числах в основном достаточно двух знаков после запя-
той.
Две десятичные цифры, представленные кодом ВСD, часто
хранят в 1 байте. Такая система записи называется уплотнен-
ным кодом ВСD (packed ВСD). Дополнение до двух в уплотнен-
ном коде ВСD не применяется, поэтому для хранения знака
обычно нужен дополнительный бит знака (sign bit). Поскольку
под число в коде BCD удобно отводить целое число байтов, бит
знака фактически занимает в памяти 4 или 8 битов.
Рассмотрим пример. Допустим, вашей программе никогда
не приходится встречаться с суммами, превышающими 10 млн.
долларов, ни в положительном, ни в отрицательном балансе.
Иначе говоря, вам нужно представлять суммы в диапазоне от
–9 999 999,99 до 9 999 999,99. Для хранения каждой суммы в
памяти нужно отвести 5 байт. Скажем, число –4 325 120,25 пя-
тью байтами представляется так:
00010100 00110010 01010001 00100000 00100101
или в шестнадцатеричном формате:
14h 32h 51h 20h 25h
Заметьте: первая слева тетрада равна 1, т. е. число отрицатель-
ное. Это и есть бит знака. Если бы число было положитель-
ным, первая тетрада равнялась бы 0. Для представления каж-
дой цифры требуется 4 бита; десятичные цифры совпадают с
шестнадцатеричными.
Чтобы хранить в памяти значения от –99 999 999,99 до 99
999 999,99, вам потребуется 6 байт: 5 для 10 цифр и еще байт
для бита знака.
(продолжение)
428
Глава двадцать третья
Такой тип записи дробных чисел называется записью с
фиксированной точкой (fixed-point)
1
, так как десятичный раз-
делитель всегда находится в определенном месте числа. В на-
шем примере после него всегда стоят две цифры. Вы вольны
отводить под дробную часть числа любое количество знаков и
использовать в одной и той же программе числа с разным ко-
личеством знаков после запятой. Но заметьте: информация о
положении разделителя вместе с числом не хранится, поэто-
му программа должна как-то узнавать, где он находится.
Формат с фиксированной точкой хорош, если вы знаете,
что числа не «перерастут» ту область памяти, которую вы для
них отвели, и что вам не понадобится увеличить количество
знаков после запятой. Но он пасует, если числа становятся
слишком большими или маленькими. Представьте, что вам
нужно предусмотреть в памяти место для записи разнообраз-
ных расстояний. Но что это будут за числа? Расстояние от Зем-
ли до Солнца составляет 150 000 000 000 метров, а боровский
радиус атома водорода — 0,00000000005 м. Чтобы заранее пре-
дусмотреть место для хранения любых промежуточных зна-
чений в формате с фиксированной точкой, вам придется от-
вести для них 12 байт памяти.
Мы, вероятно, выработаем лучший способ хранения по-
добных чисел, если вспомним о научной нотации, которую
широко применяют ученые и инженеры. В ней длинные ряды
нулей заменяются на степень десяти, благодаря чему удобно
представлять очень большие и очень маленькие числа. В на-
учной нотации число:
150 000 000 000
выглядит как:
1,5
´ 10
11
а число:
0,00000000005
— как:
5
´ 10
–11
1
Вообще-то в России в качестве десятичного разделителя традиционно используется
запятая. С другой стороны, описываемые форматы записи десятичных чисел
применяются при составлении программ, а в языках программирования в качестве
разделителя практически всегда используется точка. Поэтому в книге используются
термины «фиксированная точка» и «плавающая точка». — Прим. перев.
429
Фиксированная точка, плавающая точка
Число перед степенью 10 (в наших примерах 1,5 и 8) иногда
называют мантиссой (хотя этот термин уместней применять
по отношению к логарифмам). Я буду называть его значащей
частью числа (significand) в соответствии с компьютерной тер-
минологией.
Порядком (exponent) называется степень, в которую возво-
дится 10. В первом примере порядок равен 11; во втором –11.
Порядок позволяет узнать, на сколько знаков смещен десятич-
ный разделитель по сравнению с записью числа в формате с
фиксированной точкой.
Традиционно в научной нотации значащая часть заключе-
на между 1 (включительно) и 10. Числа, приведенные ниже,
равны:
1,5
´ 10
11
= 15
´ 10
10
= 150
´ 10
9
= 0,15
´ 10
12
= 0,015
´ 10
13
но первый вариант наиболее предпочтителен. Преобразова-
ние числа в научной нотации к стандартному виду называется
нормализацией.
Заметьте: знак показателя степени указывает на порядок
числа, но не на его положительность или отрицательность. Вот
как выглядят в научной нотации отрицательные числа:
–5,8125
´ 10
7
= –58 125 000
–5,8125
´ 10
–7
= –0,00000058125
В компьютерах научная нотация стала основой для записи
чисел в формате с плавающей точкой (floating point). В отли-
чие от формата с фиксированной точкой он идеален для хра-
нения маленьких и больших чисел. Важное отличие от тради-
ционной научной нотации в том, что в компьютерах формат с
плавающей точкой используется для двоичных чисел. Для на-
чала разберемся, как в двоичном формате выглядят дроби.
Вообще-то все проще, чем кажется. В десятичной записи
цифры справа от десятичного разделителя соответствуют от-
рицательным степеням 10. В двоичной записи цифры справа
от двоичного разделителя соответствуют отрицательным сте-
пеням 2. Например, двоичное число 101,1101 преобразуется в
десятичное так:
430
Глава двадцать третья
1
´ 4 +
0
´ 2 +
1
´ 1 +
1
¸ 2 +
1
¸ 4 +
0
¸ 8 +
1
¸ 16
Заменяем знаки деления отрицательными степенями 2:
1
´ 2
2
+
0
´ 2
1
+
1
´ 2
0
+
1
´ 2
–1
+
1
´ 2
–2
+
0
´ 2
–3
+
1
´ 2
–4
Отрицательные степени двух записываем в виде десятичных
дробей:
1
´ 4 +
0
´ 2 +
1
´ 1 +
1
´ 0,5 +
1
´ 0,25 +
0
´ 0,125 +
1
´ 0,0625
В результате получаем, что двоичное число 101,1101 экви-
валентно десятичному 5,8125.
В десятичной форме нормализованная значащая часть чис-
ла заключена между 1 и 10. Это верно и в двоичной системе:
нормализованная значащая часть всегда больше либо равна 1
и меньше 10 (2 в десятичной системе). Поэтому в двоичной
нотации число 101,1101 записывается как:
1,011101
´ 2
2
Отсюда интересный вывод: в нормализованном двоичном
числе с плавающей точкой слева от разделителя всегда стоит 1
и только 1.
В большинстве современных компьютеров и программ для
чисел с плавающей точкой применяется стандарт, введенный
431
Фиксированная точка, плавающая точка
в 1985 г. Институтом инженеров по электротехнике и радио-
электронике (Institute of Electrical and Electronics Engineers,
IEEE) и признанный Американским национальным институ-
том по стандартизации (American National Standards Institute,
ANSI), — стандарт IEEE для двоичной арифметики с плаваю-
щей точкой (IEEE Standard for Binary Floating-Point Arithmetic).
Его описание занимает всего 18 страниц, но основы кодирова-
ния двоичных чисел с плавающей точкой изложены в нем
очень ясно.
В стандарте IEEE определены два основных формата: фор-
мат с простой точностью (single precision), в котором для за-
писи числа отводится 4 байта, и формат с двойной точностью
(double precision), занимающий 8 байт.
Сначала рассмотрим формат с простой точностью. В нем
число разделяется на 3 части: 1 бит для знака (0 для положи-
тельных чисел и 1 для отрицательных), 8 бит для порядка и 23
бита для дробной значащей части числа, в которой самый млад-
ший бит стоит справа:
1 бит знака (s)
8 битов порядка (e)
23 бита дробной
значащей части (f)
Всего получается 32 бита, или 4 байта. Поскольку знача-
щая часть нормализованного двоичного числа с плавающей
точкой всегда начинается с 1, соответствующий бит в запись
числа в формате IEEE не включается. Хранится только 23-би-
товая дробная часть, хотя это не мешает говорить, что число
хранится с точностью 24 бита.
8-битовый порядок может принимать значения от 0 до 255.
Он является смещенным (biased), т. е. для нахождения истин-
ного значения порядка — с учетом знака — вы должны вы-
честь из e число, называемое смещением (bias). Для чисел про-
стой точности с плавающей точкой оно равно 127.
Порядки 0 и 255 имеют особый смысл, о котором чуть поз-
же. Если значение порядка заключено в пределах от 1 до 254,
число, представленное конкретными значениями s (бита зна-
ка), e (порядка) и f (дробная часть), равно:
(–1)
s
´ 1.f ´ 2
е–127
Знак числа вычисляется по формуле (–1)s. Если s равно 0, чис-
ло положительно (так как любое число в степени 0 равно +1),
432
Глава двадцать третья
если s равно 1, число отрицательно (так как –1 в степени 1 рав-
но –1).
Следующая часть выражения — 1.f — символизирует 23-
битовую дробную часть числа, стоящую после 1 и двоичного
разделителя (в стандарте IEEE — точка). Все это умножается
на 2 в степени e – 127.
Кроме того, в стандарте IEEE предусмотрено несколько
специальных случаев.
•
Если е равно 0, а f — 0, число равно 0. Обычно 0 представ-
ляется нулевыми значениями всех 32 битов. Если бит зна-
ка равен 1, число называется отрицательным 0. Он симво-
лизирует очень маленькое число, для записи которого цифр
и степени в простой точности недостаточно, но которое,
однако, меньше 0 (не равно ему).
•
При е = 255 и f = 0 число, в зависимости от значения s сим-
волизирует положительную или отрицательную бесконеч-
ности.
•
Если е = 255, а f не равно 0, значение считается недопусти-
мым числом и называется NaN ( Not a Number, не число).
Величина NaN часто возникает в результате некорректно-
го математического вычисления.
Самое маленькое нормализованное положительное или
отрицательное двоичное число простой точности, которое
можно представить в формате с плавающей точкой, равно:
1,00000000000000000000000
два
´ 2
–126
После запятой стоят 23 двоичных нуля. Самое большое нор-
мализованное положительное или отрицательное двоичное
число простой точности, которое можно представить в фор-
мате с плавающей точкой, равно:
1,11111111111111111111111
два
´ 2
127
В десятичном выражении эти числа приблизительно равны
1,175494351
´ 10
-38
и 3,402823466
´ 10
38
. Это и есть диапазон
чисел простой точности, которые можно представить в фор-
мате с плавающей точкой.
Вы, возможно, еще не забыли, что 10 двоичных цифр при-
близительно эквивалентны 3 десятичным. Я хочу сказать, что
двоичное число, состоящее из 10 единиц (3FFh в шестнадцате-
433
Фиксированная точка, плавающая точка
ричной системе и 1023 в десятичной), примерно равно деся-
тичному числу, состоящему из трех девяток. Иначе говоря:
2
10
» 10
3
То есть 24-битовое двоичное число простой точности в фор-
мате с плавающей точкой приблизительно эквивалентно 7-
значному десятичному числу. Поэтому говорят, что число
простой точности с плавающей точкой имеет точность до 24
двоичных или до 7 десятичных знаков. Что это значит?
Точность числа с фиксированной точкой легко определить
по его внешнему виду. В денежной сумме, например, число с
фиксированной точкой и двумя знаками после разделителя
определяется с точностью до цента. В отношении чисел с пла-
вающей точкой ничего подобного сказать нельзя. В зависимо-
сти от порядка число с плавающей точкой может быть точ-
ным до долей пенса или до нескольких тысяч долларов.
Правильнее сказать, что число простой точности с плава-
ющей точкой точно до 1 части из 2
24
или приблизительно до
6 частей из ста миллионов. В первую очередь это значит, что
если вы запишете в виде чисел простой точности с плаваю-
щей точкой величины 16 777 216 и 16 777 217, их представле-
ния будут абсолютно одинаковы! Более того, тем же значени-
ем будет представлено любое число, заключенное между ними,
например, 16 777 216,5. Все три десятичных числа будут хра-
ниться в памяти как 32-битовое значение 4В800000h. Если его
разделить на биты знака, порядка и значащей части, оно будет
выглядеть так:
0 10010111 00000000000000000000000
или:
1,00000000000000000000000
два
´ 2
24
За ним в сторону увеличения следует число:
1,00000000000000000000001
два
´ 2
24
соответствующее десятичному 16 777 218. Чаще всего хране-
ние двух близких десятичных чисел в виде одного и того же
двоичного особых трудностей не вызывает, но и забывать о
такой возможности не следует.
Допустим, вы написали для банка программу, в которой
для хранения денежных сумм в долларах и центах использу-
434
Глава двадцать третья
ются числа простой точности с плавающей точкой. Узнав, что
с точки зрения программы 262 144,00 долларов не отличаются
от 262 144,01 долларов, вы возможно, испытаете глубокое по-
трясение. Действительно, оба числа представляются в компь-
ютере так:
1.00000000000000000000000
два
´ 2
18
Вот почему при работе с долларами и центами формат с фик-
сированной точкой более предпочтителен. Разрешив точке
плавать, вы рискуете нарваться и на другие мелкие, но весьма
досадные неприятности. Например, иногда в программе вме-
сто 3,5 будет получаться 3,4999999. При работе с плавающей
точкой такие фокусы случаются довольно часто, и поделать с
этим ничего нельзя.
Если вас не устраивает простая точность, но применение
плавающей точки неизбежно, воспользуйтесь двойной точно-
стью. Числа в этом формате занимают по 8 байт памяти, рас-
пределенных так:
1 бит знака (s)
11 бит порядка (e)
52 бита дробной
значащей части (f)
Смещение порядка равно 1023 или 3FFh, поэтому число двой-
ной точности записывается так:
(–1)
s
´ 1.f ´ 2
е–1023
Для значений 0, бесконечности и NaN применяются те же
правила, что и в простой точности.
Самое маленькое положительное или отрицательное чис-
ло двойной точности с плавающей точкой равно:
1.0000000000000000000000000000000000000000000000000000
два
´ 2
-1022
После двоичной точки стоит 52 нуля. Самое большое число
равно:
1.1111111111111111111111111111111111111111111111111111
два
´ 2
1023
Соответствующий диапазон десятичных чисел — приблизи-
тельно от 2,2250738585072014 ххх 10
–308
до 1,797693138623158
´ 10
308
.
53 бита значащей части числа (с учетом неуказываемого пер-
вого бита, который всегда равен 1) примерно эквивалентны 16
435
Фиксированная точка, плавающая точка
десятичным цифрам. Это, конечно, намного больше, чем в
простой точности, но все равно от одинакового представле-
ния двух близких десятичных чисел нам никуда не деться. На-
пример, в двоичном представлении число 140 737 488 355 328,00
не отличается от 140 737 488 355 328,01. Оба хранятся как
64-битовая величина 42Е0000000000000h, равная:
1.0000000000000000000000000000000000000000000000000000
два
´ 2
47
Разумеется, разработка формата для хранения чисел с пла-
вающей точкой в памяти компьютера — лишь небольшая
часть работы по практическому использованию этих чисел в
ассемблерных программах. Если бы вы создавали компьютер
на необитаемом острове, то столкнулись бы с необходимос-
тью написания программ для сложения, вычитания, умноже-
ния и деления чисел с плавающей точкой. К счастью, их мож-
но разбить на функции для сложения, вычитания, умножения
и деления целых чисел, работать с которыми вы уже умеете.
Например, сложение двух чисел с плавающей точкой за-
ключается в сложении их значащих частей; труднее всего здесь
разобраться с порядками. Рассмотрим пример:
(1,1101
´ 2
5
) + (1,0010
´ 2
2
)
Здесь нужно сложить 11101 и 10010, но не просто, а с прира-
щением разрядности первого числа на величину, определяе-
мую по разности порядков. Первый порядок на 3 больше вто-
рого, поэтому добавляем к первому числу 3 нуля и складыва-
ем 11101000 и 10010. Итоговая сумма равна 1,1111010
´ 2
5
. Иног-
да порядки различаются столь существенно, что сумма совер-
шенно не отличается от большего из слагаемых. Так произой-
дет, например, при сложении расстояния от Земли до Солнца
с радиусом атома водорода.
Умножение чисел с плавающей точкой равносильно умно-
жению их значащих частей и сложению порядков. Обе опера-
ции не выходят за рамки целочисленной арифметики.
Следующий уровень сложности в вычислениях с плаваю-
щей точкой — вычисление корней, логарифмов, показатель-
ных и тригонометрических функций. Но все эти функции так-
же можно разложить на четыре основные операции: сложе-
ние, вычитание, умножение и деление. Так, синус вычисляет-
ся с помощью ряда:
436
Глава двадцать третья
sin(
x) = x -
x
3
3!
+
x
5
5!
-
x
7
7!
+...
Здесь аргумент х измеряется не в градусах, а в радианах (360°
равно 2
p радиан), а восклицательным знаком обозначен фак-
ториал числа, равный произведению всех целых чисел от еди-
ницы и до этого числа. Например, 5! = 1
´ 2 ´ 3 ´ 4 ´ 5. Таким
образом, при вычислении числителя и знаменателя в каждом
члене ряда мы используем умножение, делим числитель на
знаменатель, а затем складываем и вычитаем результаты. Про-
сто? Да не совсем. Самая неприятная часть этого выражения
— многоточие в конце. Оно означает, что теоретически вы-
числение продолжается бесконечно. Но на практике вычис-
лять это выражение для любого x не нужно. Синус — перио-
дическая функция, поэтому его достаточно рассчитать для x в
пределах от 0 до
p/2, а затем по простым формулам получить
значения синуса для произвольного x. Чтобы рассчитать sin x
при x в пределах от 0 до
p/2 с точностью до 53 бит, достаточно
учесть в этом разложении с десяток слагаемых.
«Что же получается? — скажете вы. — Компьютеры при-
званы облегчать людям жизнь, а мы вопреки этому постоян-
но сталкиваемся с необходимостью написания все новых и
новых программ!» Но в этом-то и прелесть программирова-
ния. Как только кто-то написал программы для вычислений с
плавающей точкой, их могут использовать и другие. А с напи-
санием таких программ заминки не возникает. Расчеты с пла-
вающей точкой жизненно важны в научных и инженерных
программах, поэтому их реализации всегда придается самое
большое значение. В начале компьютерной эпохи написание
программ для вычислений с плавающей точкой всегда было
одной из первых задач, стоявших перед создателями новой
модели компьютера.
На самом деле имеет смысл создать для работы с плаваю-
щей точкой специальные машинные команды! Если выпол-
нять операции с плавающей точкой на аппаратном уровне, как
умножение и деление в 16-битовых микропроцессорах, слож-
ные математические расчеты будут проводиться гораздо быс-
трее. Конечно, сказать легче, чем сделать. Но вычисления с
плавающей точкой настолько важны, что специальное обору-
дование для них создано уже давно.
437
Фиксированная точка, плавающая точка
В 1954 г. выпущен IBM 704 — первый коммерческий ком-
пьютер, имевший аппаратное обеспечение для работы с пла-
вающей точкой. Все числа в нем хранились как 36-битовые
величины: 27 битов под значащую часть, 8 битов для порядка
и 1 бит для знака. В процессоре имелись схемы для сложения,
вычитания, умножения и деления чисел с плавающей точкой.
Другие функции реализовывались программно.
В настольных компьютерах аппаратное обеспечение для
арифметики с плавающей точкой появилось в 1980 г., когда
компания Intel выпустила микросхему 8087. В наши дни мик-
росхемы этого типа называют математическими сопроцессо-
рами. Название сопроцессор (coprocessor) означает, что приме-
нять эту микросхему отдельно от процессора нельзя. Сопро-
цессор 8087 работал с первыми 16-разрядными микропроцес-
сорами Intel 8086 и 8088.
Сопроцессор 8087 — микросхема с 40 выводами, в кото-
рой используются многие из сигналов микросхем 8086 и 8088.
Посредством этих сигналов процессор и сопроцессор взаимо-
действуют друг с другом. Когда процессор считывает специ-
альную команду (ESC), управление берет на себя сопроцессор,
выполняющий следующий за этой командой машинный код
— одну из 68 команд для вычисления логарифма, тригономет-
рических функций, возведения в степень и пр. Типы данных
основаны на стандарте IEEE. В свое время сопроцессор 8087
считался самой сложной интегральной схемой.
Можете считать сопроцессор маленьким самостоятельным
компьютером. Получив команду на выполнение определенно-
го расчета с плавающей точкой (например, команду FSQRT для
вычисления квадратного корня), сопроцессор запускает набор
собственных команд, записанных в ПЗУ. Внутренние команды
сопроцессора называются микрокодом. Обычно выполнение
микрокода сопряжено с вычислениями в цикле, поэтому резуль-
тат готов не сразу. И все же сопроцессор позволяет ускорить
вычисления по крайней мере в 10 раз по сравнению с программ-
ной реализацией операций с плавающей точкой.
На материнской плате первого IBM PC рядом с микросхе-
мой 8088 имелось 40-контактное гнездо для сопроцессора 8087.
К сожалению, при продаже компьютера оно пустовало.
Пользователи, нуждавшиеся в высокой скорости вычислений,
покупали и устанавливали сопроцессор 8087 самостоятельно.
438
Глава двадцать третья
Но даже после его установки не все приложения начинали ра-
ботать быстрее. Текстовому редактору, например, арифмети-
ка с плавающей точкой почти ни к чему. Но даже программы
с обильными математическими расчетами, например, элект-
ронные таблицы, зачастую благотворного влияния сопроцес-
сора на себе не испытывали.
Мы уже убедились, что для сопроцессора программист дол-
жен вставлять в программу специальные машинные коды. Но
сопроцессор не был стандартным оборудованием, и потому
многие программисты себя этим не утруждали. Им ведь все
равно приходилось писать подпрограммы для работы с пла-
вающей точкой для тех пользователей, у которых не было со-
процессора, поэтому микросхема 8087 не избавляла их от ра-
боты, а, напротив, усложняла ее. Позже программисты научи-
лись писать приложения так, что, если сопроцессор был на
компьютере, он использовался, а если нет — его работа моде-
лировалась программно.
Позже Intel выпустила сопроцессор 287 для процессора 286
и сопроцессор 387 для процессора 386. В 1989 г. сопроцессор
наконец перестал был отдельным элементом оборудования,
устанавливаемым по желанию, — в процессор Intel 486DX он
был встроен! Правда, в 1991 г. Intel снова вернулась к старой
схеме, выпустив дешевый процессор 486SX без встроенного
сопроцессора и сопроцессор 487SX к нему. Однако в 1993 г. с
появлением процессоров серии Pentium сопроцессор снова
стал частью процессора, теперь, вероятно, уже навсегда. Ком-
пания Motorola объединила сопроцессор с микропроцессором
68040 в 1990 г. До этого сопроцессоры 68881 и 68882 для мик-
ропроцессоров семейства 68000 продавались отдельно. Встро-
енное оборудование для работы с плавающей точкой имеется
и в процессорах PowerPC.
Аппаратное обеспечение для арифметики с плавающей
точкой — хороший подарок для человека, уставшего програм-
мировать на языке ассемблера. Но его значение меркнет в срав-
нении с другим усовершенствованием, начало которому было
положено в 1950-е годы. Наша следующая остановка — языки
программирования.
|