Для представления отрицательных чисел используется. Формат представления чисел с плавающей запятой. Алгоритм представления числа с плавающей запятой

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

Система счисления

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

Чтобы перевести привычные для нас десятичные числа к виду, понятному компьютеру, нужно воспользоваться описанным ниже алгоритмом. Существуют и специализированные калькуляторы.

Итак, для того чтобы перевести число в двоичную систему счисления, нужно взять выбранное нами значение и поделить его на 2. После этого мы получим результат и остаток (0 или 1). Результат опять делим 2 и запоминаем остаток. Данную процедуру нужно повторять до тех пор, пока в итоге также не окажется 0 или 1. Затем записываем конечное значение и остатки в обратном порядке, как мы их получали.

Именно так и происходит представление чисел в компьютере. Любое число записывается в двоичной форме, а потом занимает ячейку памяти.

Память

Как вам должно быть уже известно, минимальная единица измерения информации составляет 1 бит. Как мы уже выяснили, представление чисел в компьютере происходит в двоичном формате. Таким образом, каждый бит памяти будет занят одним значением - 1 или 0.

Для хранения используются ячейки. Каждая такая единица содержит до 8 бит информации. Поэтому можно сделать вывод, что минимальное значение в каждом отрезке памяти может составлять 1 байт или быть восьмизначным двоичным числом.

Целые

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

Начнем мы с самого простого варианта, коим является представление целых чисел в компьютере. Память ПК отводит под этот процесс до смешного малое количество ячеек - всего одну. Таким образом, максимум в одном слоте могут быть значения от 0 до 11111111. Давайте переведём максимальное число в привычную нам форму записи.
Х = 1 × 2 7 + 1 × 2 6 + 1 × 2 5 + 1 × 2 4 + 1 × 2 3 + 1 × 2 2 + 1 × 2 1 + 1 × 2 0 = 1 × 2 8 - 1 = 255.

Теперь мы видим, что в одной ячейке памяти может располагаться значение от 0 до 255. Однако это относится исключительно к целым неотрицательным числам. Если же компьютеру понадобится записать отрицательное значение, всё пройдет немного по-другому.

Отрицательные числа

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

Если цифра отрицательная, то записывается "1", если положительная, то "0". Для простоты запоминания можно провести такую аналогию: если знак есть, то ставим 1, если его нет, то ничего (0).

Оставшиеся 15 бит информации отводятся под число. Аналогично предыдущему случаю, в них можно поместить максимум пятнадцать единиц. Стоит отметить, что запись отрицательных и положительных чисел существенно отличается друг от друга.

Для того чтобы разместить в 2 ячейках памяти значение больше нуля или равное ему, используется так называемый прямой код. Данная операция производится так же, как и было описано, а максимальное А = 32766, если использовать Сразу хочется отметить, что в данном случае "0" относится к положительным.

Примеры

Представление целых чисел в памяти компьютера не является такой уж трудной задачей. Хотя она немного усложняется, если речь идет об отрицательном значении. Для записи числа, которое меньше нуля, используется дополнительный код.

Чтобы его получить, машина производит ряд вспомогательных операций.

  1. Сначала записывается модуль отрицательного числа в двоичном счислении. То есть компьютер запоминает аналогичное, но положительное значение.
  2. Затем проводится инвертирование каждого бита памяти. Для этого все единицы заменяются нулями и наоборот.
  3. Прибавляем "1" к полученному результату. Это и будет дополнительный код.

Приведем наглядный пример. Пусть у нас есть число Х = - 131. Сначала получаем его модуль |Х|= 131. Затем переводим в двоичную систему и записываем в 16 ячеек. Получим Х = 0000000010000011. После инвертирования Х=1111111101111100. Добавляем к нему "1" и получаем обратный код Х=1111111101111101. Для записи в 16-битную ячейку памяти минимальным числом является Х = - (2 15) = - 32767.

Длинные целые

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

Процесс записи абсолютно не отличается от представленного выше. Так что мы просто приведем диапазон чисел, которые могут храниться в данном типе.

Х мах =2 147 483 647.

Х min =- 2 147 483 648.

Данных значений в большинстве случаев достаточно для того, чтобы записывать и проводить операции с данными.

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

Плавающая запятая

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

Любое число может быть представлено в следующей форме Х = m * р п. Где m - это мантисса числа, р - основание системы счисления и п - порядок числа.

Для стандартизации записи чисел с плавающей запятой используется следующее условие, согласно которому модуль мантиссы должен быть больше или равен 1/п и меньше 1.

Пусть нам дано число 666,66. Приведём его к экспоненциальной форме. Получится Х = 0,66666 * 10 3 . Р = 10 и п = 3.

На хранение значений с плавающей запятой обычно выделяется 4 или 8 байт (32 или 64 бита). В первом случае это называется числом обычной точности, а во втором - двойной точности.

Из 4 байт, выделенных под хранение цифр, 1 (8 разрядов) отдается под данные о порядке и его знаке, а 3 байта (24 разряда) уходят на хранение мантиссы и её знака по тем же принципам, что и для целочисленных значений. Зная это, мы можем провести нехитрые расчеты.

Максимальное значение п = 1111111 2 = 127 10 . Исходя из него, мы можем получить максимальный размер числа, которое может храниться в памяти компьютера. Х=2 127 . Теперь мы можем вычислить максимально возможную мантиссу. Она будет равна 2 23 - 1 ≥ 2 23 = 2 (10 × 2,3) ≥ 1000 2,3 = 10 (3 × 2,3) ≥ 10 7 . В итоге, мы получили приближенное значение.

Если теперь мы объединим оба расчета, то получим значение, которое может быть записано без потерь в 4 байта памяти. Оно будет равно Х = 1,701411 * 10 38 . Остальные цифры были отброшены, поскольку именно такую точность позволяет иметь данный способ записи.

Двойная точность

Поскольку все вычисления были расписаны и объяснены в предыдущем пункте, здесь мы расскажем всё очень коротко. Для чисел с двойной точностью обычно выделяется 11 разрядов для порядка и его знака, а также 53 разряда для мантиссы.

П = 1111111111 2 = 1023 10 .

М = 2 52 -1 = 2 (10*5.2) = 1000 5.2 = 10 15.6 . Округляем в большую сторону и получаем максимальное число Х = 2 1023 с точностью до "м".

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

Общие сведения.

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

Ниже рассматриваются следующие типы данных:

● знаковые и беззнаковые целые , используемые для представления целых чи-сел в виде двоичных кодов и выполнения над ними арифметических операций по правилам двоичной арифметики;

двоично–десятичные целые , предназначенные для представления и обработки десятичных чисел;

булев тип данных , поддерживающий правила алгебры–логики (булевой алгебры);

типы с фиксированной и плавающей точкой , предназначенные для представ-ления и обработки вещественных чисел.

Выбор типа данных определяется командой программы. Например, при вы-полнении арифметической команды данные трактуются как целые числа, операн-ды в логической операции принимаются как булев тип данных, а 16–битный указа-тель используется командой для доступа к данным в текущем сегменте.

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

О формах представления чисел.

Для представления чисел широко исполь-зуются две формы: естественная и нормальная.

При естественной форме представления число имеет единственный вид записи, например: +195 - целое положительное число; –195 - целое отрица-тельное число; +0,025 - правильная положительная дробь; –195,025 - непра-вильная отрицательная дробь. Эта форма используется для представления целых чисел и чисел с фиксированной точкой (запятой).

При нормальной форме представления число записывается в виде

где М, П - мантисса и порядок числа.

Для нормальной формы представления характерна неоднозначная запись чис-ла, например: +195.025 = +195025 . 10 –3 = +19.5025 . 10 1 = +0.195025 . 10 3 . Как видно из примера, положение точки мантиссы зависит от значения порядка П. С изменением П (что всегда происходит в процессе вычислений) точка как бы начина-ет плавать. Поэтому нормальную форму (2.3.1) называют также формой пред-ставления чисел с плавающей точкой.

Числовая (как и любая другая) информация, подлежащая процессорной обра-ботке, представляется в виде

–разрядных двоичных кодов, для хранения которых используются ячейки памяти. Двоичные коды чисел имеют различные форматы.

Формат числа представляет собой совокупность разрядов (разрядную сетку), разделенную на отдельные поля: поле знака числа, поле модуля числа, поле ман-тиссы, поле модуля порядка и др. Для нумерации разрядов полей используется последовательность чисел, начиная с нуля (0, 1, 2, 3, …).

Беззнаковые целые.

Этот тип данных используется для представления нуля и положительных значений целых чисел.

На рис. 2.3.1 , а приведены форматы 8–разрядных целых чисел. Знаковый бит отсутствует, поэтому диапазон представления чисел составляет 0…2

Разрядность двоичного кода совпадает с разрядностью числа.

Знаковые целые.

Операцию вычитания двух положительных А и В чисел мож-но рассматривать как операцию алгебраического сложения чисел с разными зна-ками: А – В = А + (–

). Поэтому для замены арифметической операции вычитания операцией алгебраического сложения необходимо каким–то образом предста-вить знак числа. Обычно для знака двоичного числа отводится дополнительный разряд. Знак числа указывается в самом старшем разряде: 0 соответствует поло-жительному знаку « + » числа, 1 - отрицательному знаку « – ».

Для представления чисел со знаком широкое распространение получил до-полнительный код.

Для представления целых положительных двоичных чисел в

–разрядном до-полнительном коде все старшие незначащие разряды (включая знаковый) необ-ходимо заполнить нулями.

Для представления отрицательных чисел необходимо:

● проинвертировать все значащие цифровые разряды (модуль) числа;

● к полученному значению прибавить единицу;

● все старшие незначащие разряды (включая знаковый) заполнить единицами.

Например, 8–разрядный дополнительный код для положительного числа +6 имеет вид 00000110, для отрицательного числа – 6 - 11111010.

На рис. 2.3.1, б приведены форматы 8–разрядных знаковых чисел в допол-нительном коде. Диапазон их представления составляет – 2 (

–1) - разрядность значащей части числа. Современные микропроцессоры поддерживают знаковые целые длиной 16, 32 и 64 бит. Обычно используется два формата целых чисел: короткий с числом разрядов

и длинный с числом разря-дов 2

В процессе расчетов используется длинный формат, результаты выводят-ся в коротком формате. Если количество значащих разрядов модуля числа пре-вышает (

– 1), происходит переполнение разрядной сетки, приводящее к ошибке в представлении числа из–за потери старших разрядов модуля. После выполне-ния арифметических операций выход результата за диапазон отмечается уста-новкой а единицу флага переполнения О

Числа с фиксированной точкой.

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

Выбранное количество значащих разрядов числа.

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

При нарушении условия (2.3.2) число А Ф имеет целую часть, которая теряется, так как не попадает в разрядную сетку из–за переполнения. Поэтому при опреде-лении масштабного коэффициента К следует исходить из максимального значе-ния модуля задействованных при решении задачи чисел, приняв К> | А |

Тогда условие (2.3.2) для А Ф = А/К будет выполняться.

На рис. 2.3.2, а приведен формат компьютерного представления чисел А Ф с фиксированной точкой. При занесении числа А Ф в ячейку памяти свободные младшие разряды разрядной сетки заполняются нулями. Если число

значащих разрядов модуля |

– 1, то младшие разряды модуля, которые не по-местились в

–разрядной сетке, теряются. Это приводит к погрешности, абсолютное значение которой меньше единицы младшего разряда разрядной сетки, т. е.

32 абсолютная погрешность

0.5×10 – 30х0.3 = 0.5×10 – 9

Пусть заданы два числа А = –1010,101 2 и В = +10,10101 2 , для которых |

Поэтому масштаб-ный коэффициент К > |

2 4 = 10000 2 . Степень 4 свидетельствует о необходимости сдвига на 4 разря-да вправо исходных чисел

Действительно

А. К= –1010,101 . 10000 =

–0.1010101 2 ;

В Ф = В. К = 10,10101 . 10000 = 0,001010101 2 . Форматы представления чисел А Ф и В Ф показаны на рис. 2.3.2,6, в. Для сохранения точности компьютерного представления числа В Ф необходимо расширить разрядную сетку до 10 разрядов.

К достоинству представления чисел в форме с фиксированной точкой следует отнести простоту выполнения арифметических операций. Недостатки проявляют-ся в том, что:

● необходимо производить выбор масштабных коэффициентов;

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

Булевы типы.

Булевы величины являются беззнаковыми и используются при логических операциях

и др. Операция выполняется над от-дельными битами. Булевы операнды обрабатываются по частям, если их разряд-ность превышает разрядность процессора.

Двоично–десятичные целые.

В повседневной жизни человек пользуется де-сятичной системой счисления. Для хранения и обработки десятичных чисел в цифровых устройствах их представляют в виде двоичного кода. Представление десятичного числа, в котором каждая десятичная цифра отображается в виде двоичных символов 0 и 1, называют двоично–десятичным кодом. Так как алфавит десятичной системы состоит из 10 цифр, для записи каждой десятичной цифры выделяется слово, содержащее не менее четырех разрядов. Наиболее часто ис-пользуется 4–разрядное слово, именуемое тетрадой или полубайтом. С помощью тетрад вместо требуемых 10 можно получить 2 4 = 16 различных комбинаций, со-ставленных символов 0 и 1. При двоично–десятичном кодировании различным десятичным цифрам должны соответствовать различные комбинации символов О и 1, т. е. разрешены только 10 комбинаций из 16. Наличие разрешенных и за-прещенных комбинаций - важное свойство двоично–десятичных кодов. Это свойство отличает их от обычных позиционных систем счисления, в которых все комбинации разрешены. Общее количество различных разрешенных 4–разрядных кодов (тетрад), определяемое сочетаниями из 16 элементов по 10, составляет: С 10 16 = 18008. Широкое распространение получил так называемый код 8421, в котором используется первые десять значений двоичных чисел от 0000 (0 10) до 1001(9 10).

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

На рис. 2.3.3 приведен формат двоично–десятичного числа, содержащий 18 тетрад (

0) и знаковый разряд

(в остальных разрядах старшего байта установлены нулевые значения). Каждая тетрада соответствует одному разряду десятичного числа.

Числа с плавающей точкой.

Во многих случаях для проведения расчетов не-обходимо представлять числа с высокой точностью в широком диапазоне значе-ний. Указанным требованиям отвечает нормальная форма чисел (2.3.1). Для вы-явления особенностей ее использования для представления чисел с плавающей точкой в цифровых системах будем полагать, что:

● для записи мантиссы используется (

1)–разрядный двоичный код, причем самый старший (

–й) разряд определяет знак мантиссы (числа), остальные разряды - модуль мантиссы. Значение модуля мантиссы |М| < 1, что соот-ветствует фиксации точки перед значащими цифрами (разрядами) модуля мантиссы;

● для записи порядка П используется (р + 1)–разрядный двоичный код, причем самый старший (р–й) разряд определяет знак порядка, остальные разряды - модуль порядка. Порядок П (целое число) указывает на действительное положение точки в числе.

На рис. 2.3.4, а приведен формат числа с плавающей точкой.

Точность представления чисел (2.3.1) зависит от количества значащих цифр (разрядов) мантиссы. Для повышения точности числа с плавающей точкой пред-ставляются в нормализованной форме, признаком которой служит наличие значащей цифры (единицы для

2) в самом старшем разряде модуля ман-тиссы. Значение модуля нормализованной мантиссы при

2 лежит в пределах 2 –1 ≤ |М| < 1 (для любых порядков П). В нормализованной форме могут быть представлены все числа из некоторого диапазона за исключением нуля.

Представим в формате с плавающей точкой двоичные числа А = +10010.10101 и В = –111.0101. Запишем А и В в нормализованной форме

А = +0.1001010101 . 2 5 , В= –0.1110101000 . 2 –3 .

На основании (2.3.4) записываем модули мантиссы |М

| = 1001010101 2 , |М

| = 1110101000 2 и моду-ли порядка в двоичной системе исчисления |П А | = 5 10 = 0101 2 , |П

| = 3 10 = 0011 2 . Выбираем общее число разрядов разрядной сетки

Р = 16. Принимаем количество разрядов для модуля мантиссы, равное 10, для модуля порядка - 4.

Форматы чисел А и В показаны на рис. 2.3.4, 6, в. Мантисса и порядок операнда В, имеющие отри-цательное значение, представлены в дополнительном коде:

|# + 1 = 0001010111 + 1 = 0001011110;

|# + 1 = 0011 + 1 = 0100, где # - инверсия.

Поскольку абсолютная погрешность представления чисел с плавающей точкой зависит от порядка П, дадим оценку относительной погрешности:

/ 2 –1 = 2 –(

Абсолютная погрешность представления модуля

–разрядной мантиссы; |

22 –1 - минимальное значение нормализованного модуля мантиссы.

Отметим, что в стандарте

754/854 используется порядок в форме П = Р – Е, где Е =

Смещение порядка; Р макс = 2Е. Это позволило исключить поле

знака порядка в формате представления чисел.

В далекие времена, для IT-индустрии это 70-е годы прошлого века, ученые-математики (так раньше назывались программисты) сражались как Дон-Кихоты в неравном бою с компьютерами, которые тогда были размером с маленькие ветряные мельницы. Задачи ставились серьезные: поиск вражеских подлодок в океане по снимкам с орбиты, расчет баллистики ракет дальнего действия, и прочее. Для их решения компьютер должен оперировать действительными числами, которых, как известно, континуум, тогда как память конечна. Поэтому приходится отображать этот континуум на конечное множество нулей и единиц. В поисках компромисса между скоростью, размером и точностью представления ученые предложили числа с плавающей запятой (или плавающей точкой, если по-буржуйски).

Арифметика с плавающей запятой почему-то считается экзотической областью компьютерных наук, учитывая, что соответствующие типы данных присутствуют в каждом языке программирования. Я сам, если честно, никогда не придавал особого значения компьютерной арифметике, пока решая одну и ту же задачу на CPU и GPU получил разный результат. Оказалось, что в потайных углах этой области скрываются очень любопытные и странные явления: некоммутативность и неассоциативность арифметических операций, ноль со знаком, разность неравных чисел дает ноль, и прочее. Корни этого айсберга уходят глубоко в математику, а я под катом постараюсь обрисовать лишь то, что лежит на поверхности.

1. Основы

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

Число с плавающей запятой состоит из набора отдельных разрядов, условно разделенных на знак, экспоненту порядок и мантиссу. Порядок и мантисса - целые числа, которые вместе со знаком дают представление числа с плавающей запятой в следующем виде:

Математически это записывается так:

(-1) s × M × B E , где s - знак, B-основание, E - порядок, а M - мантисса.

Основание определяет систему счисления разрядов. Математически доказано, что числа с плавающей запятой с базой B=2 (двоичное представление) наиболее устойчивы к ошибкам округления, поэтому на практике встречаются только базы 2 и, реже, 10. Для дальнейшего изложения будем всегда полагать B=2, и формула числа с плавающей запятой будет иметь вид:

(-1) s × M × 2 E

Что такое мантисса и порядок? Мантисса – это целое число фиксированной длины, которое представляет старшие разряды действительного числа. Допустим наша мантисса состоит из трех бит (|M|=3). Возьмем, например, число «5», которое в двоичной системе будет равно 101 2 . Старший бит соответствует 2 2 =4, средний (который у нас равен нулю) 2 1 =2, а младший 2 0 =1. Порядок – это степень базы (двойки) старшего разряда. В нашем случае E=2. Такие числа удобно записывать в так называемом «научном» стандартном виде, например «1.01e+2». Сразу видно, что мантисса состоит из трех знаков, а порядок равен двум.

Допустим мы хотим получить дробное число, используя те же 3 бита мантиссы. Мы можем это сделать, если возьмем, скажем, E=1. Тогда наше число будет равно

1,01e+1 = 1×2 1 +0×2 0 +1×2 -1 =2+0,5=2,5

Здесь, поскольку E=1, степень двойки первого разряда (который идет перед запятой), равна «1». Два других разряда, расположенных правее (после запятой), обеспечивают вклад 2 E-1 и 2 E-2 (2 0 и 2 -1 соответственно). Очевидно, что регулируя E одно и то же число можно представить по-разному. Рассмотрим пример с длиной мантиссы |M|=4. Число «2» можно представить в следующем виде:

2 = 10 (в двоичной системе) = 1.000e+1 = 0.100e+2 = 0.010e+3. (E=1, E=2, E=3 соответственно)

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

Это экономит один бит, так как неявную единицу не нужно хранить в памяти, и обеспечивает уникальность представления числа. В нашем примере «2» имеет единственное нормализованное представление («1.000e+1»), а мантисса хранится в памяти как «000», т.к. старшая единица подразумевается неявно. Но в нормализованном представлении чисел возникает новая проблема - в такой форме невозможно представить ноль.

Строго говоря, нормализованное число имеет следующий вид:

(-1) s × 1.M × 2 E .

Качество решения задач во многом зависит от выбора представления чисел с плавающей запятой. Мы плавно подошли к проблеме стандартизации такого представления.

2. Немного истории

В 60-е и 70-е годы не было единого стандарта представления чисел с плавающей запятой, способов округления, арифметических операций. В результате программы были крайне не портабельны. Но еще большей проблемой было то, что у разных компьютеров были свои «странности» и их нужно было знать и учитывать в программе. Например, разница двух не равных чисел возвращала ноль. В результате выражения «X=Y» и «X-Y=0» вступали в противоречие. Умельцы обходили эту проблему очень хитрыми трюками, например, делали присваивание «X=(X-X)+X» перед операциями умножения и деления, чтобы избежать проблем.

Инициатива создать единый стандарт для представления чисел с плавающей запятой подозрительно совпала с попытками в 1976 году компанией Intel разработать «лучшую» арифметику для новых сопроцессоров к 8086 и i432. За разработку взялись ученые киты в этой области, проф. Джон Палмер и Уильям Кэхэн. Последний в своем интервью высказал мнение, что серьезность, с которой Intel разрабатывала свою арифметику, заставила другие компании объединиться и начать процесс стандартизации.

Все были настроены серьезно, ведь очень выгодно продвинуть свою архитектуру и сделать ее стандартной. Свои предложения представили компании DEC, National Superconductor, Zilog, Motorola. Производители мейнфреймов Cray и IBM наблюдали со стороны. Компания Intel, разумеется, тоже представила свою новую арифметику. Авторами предложенной спецификации стали Уильям Кэхэн, Джероми Кунен и Гарольд Стоун и их предложение сразу прозвали «K-C-S».

Практически сразу же были отброшены все предложения, кроме двух: VAX от DEC и «K-C-S» от Intel. Спецификация VAX была значительно проще, уже была реализована в компьютерах PDP-11, и было понятно, как на ней получить максимальную производительность. С другой стороны в «K-C-S» содержалось много полезной функциональности, такой как «специальные» и «денормализованные» числа (подробности ниже).

В «K-C-S» все арифметические алгоритмы заданы строго и требуется, чтобы в реализации результат с ними совпадал. Это позволяет выводить строгие выкладки в рамках этой спецификации. Если раньше математик решал задачу численными методами и доказывал свойства решения, не было никакой гарантии, что эти свойства сохранятся в программе. Строгость арифметики «K-C-S» сделала возможным доказательство теорем, опираясь на арифметику с плавающей запятой.

Компания DEC сделала все, чтобы ее спецификацию сделали стандартом. Она даже заручилась поддержкой некоторых авторитетных ученых в том, что арифметика «K-C-S» в принципе не может достигнуть такой же производительности, как у DEC. Ирония в том, что Intel знала, как сделать свою спецификацию такой же производительной, но эти хитрости были коммерческой тайной. Если бы Intel не уступила и не открыла часть секретов, она бы не смогла сдержать натиск DEC.

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

3. Представление чисел с плавающей запятой сегодня

Разработчики «K-C-S» победили и теперь их детище воплотилось в стандарт IEEE754. Числа с плавающей запятой в нем представлены в виде знака (s), мантиссы (M) и порядка (E) следующим образом:

(-1) s × 1.M × 2 E

Замечание. В новом стандарте IEE754-2008 кроме чисел с основанием 2 присутствуют числа с основанием 10, так называемые десятичные (decimal) числа с плавающей запятой.

Чтобы не загромождать читателя чрезмерной информацией, которую можно найти в Википедии , рассмотрим только один тип данных, с одинарной точностью (float). Числа с половинной, двойной и расширенной точностью обладают теми же особенностями, но имеют другой диапазон порядка и мантиссы. В числах одинарной точности (float/single) порядок состоит из 8 бит, а мантисса – из 23. Эффективный порядок определяется как E-127. Например, число 0,15625 будет записано в памяти как

Рисунок взят из Википедии

В этом примере:

  • Знак s=0 (положительное число)
  • Порядок E=01111100 2 -127 10 = -3
  • Мантисса M = 1.01 2 (первая единица не явная)
  • В результате наше число F = 1.01 2 e-3 = 2 -3 +2 -5 = 0,125 + 0,03125 = 0,15625

Чуть более подробное объяснение

Здесь мы имеем дело с двоичным представлением числа «101» со сдвигом запятой на несколько разрядов влево. 1,01 - это двоичное представление, означающее 1×2 0 + 0×2 -1 + 1×2 -2 . Сдвинув запятую на три позиции влево получим 1,01e-3 = 1×2 -3 + 0×2 -4 + 1×2 -5 = 1×0,125 + 0×0,0625 + 1×0,03125 = 0,125 + 0,03125 = 0,15625.

3.1 Специальные числа: ноль, бесконечность и неопределенность
В IEEE754 число «0» представляется значением с порядком, равным E=E min -1 (для single это -127) и нулевой мантиссой. Введение нуля как самостоятельного числа (т.к. в нормализованном представлении нельзя представить ноль) позволило избежать многих странностей в арифметике. И хоть операции с нулем нужно обрабатывать отдельно, обычно они выполняются быстрее, чем с обычными числами.

Также в IEEE754 предусмотрено представление для специальных чисел, работа с которыми вызывает исключение. К таким числам относится бесконечность (±∞) и неопределенность (NaN). Эти числа позволяет вернуть адекватное значение при переполнении. Бесконечности представлены как числа с порядком E=E max +1 и нулевой мантиссой. Получить бесконечность можно при переполнении и при делении ненулевого числа на ноль. Бесконечность при делении разработчики определили исходя из существования пределов, когда делимое и делитель стремиться к какому-то числу. Соответственно, c/0==±∞ (например, 3/0=+∞, а -3/0=-∞), так как если делимое стремиться к константе, а делитель к нулю, предел равен бесконечности. При 0/0 предел не существует, поэтому результатом будет неопределенность.

Неопределенность или NaN (от not a number) – это представление, придуманное для того, чтобы арифметическая операция могла всегда вернуть какое-то не бессмысленное значение. В IEEE754 NaN представлен как число, в котором E=E max +1, а мантисса не нулевая. Любая операция с NaN возвращает NaN. При желании в мантиссу можно записывать информацию, которую программа сможет интерпретировать. Стандартом это не оговорено и мантисса чаще всего игнорируется.

Как можно получить NaN? Одним из следующих способов:

  • ∞+(- ∞)
  • 0 × ∞
  • 0/0, ∞/∞
  • sqrt(x), где x<0
По определению NaN ≠ NaN, поэтому, для проверки значения переменной нужно просто сравнить ее с собой.
Зачем нулю знак (или +0 vs -0)
Любознательный читатель вероятно уже замелил заметил, что в описанном представлении чисел с плавающей запятой существует два нуля, которые отличаются только знаком. Так, 3·(+0)=+0, а 3·(-0)=-0. Но при сравнении +0=-0. В стандарте знак сохранили умышленно, чтобы выражения, которые в результате переполнения или потери значимости превращаются в бесконечность или в ноль, при умножении и делении все же могли представить максимально корректный результат. Например, если бы у нуля не было знака, выражение 1/(1/x)=x не выполнялось бы верно при x=±∞, так как 1/∞ и 1/-∞ равны 0.

Еще один пример:
(+∞/0) + ∞ = +∞, тогда как (+∞/-0) +∞ = NaN

Чем бесконечность в данном случае лучше, чем NaN? Тем, что если в арифметическом выражении появился NaN, результатом всего выражения всегда будет NaN. Если же в выражении встретилась бесконечность, то результатом может быть ноль, бесконечность или обычное число с плавающей запятой. Например, 1/∞=0.

3.3 Денормализованные числа
Что такое субнормальные денормализованные (subnormal) числа рассмотрим на простом примере. Пусть имеем нормализованное представление с длиной мантиссы |M|=2 бита (+ один бит нормализации) и диапазоном значений порядка -1≤E≤2. В этом случае получим 16 чисел:

Крупными штрихами показаны числа с мантиссой, равной 1,00. Видно, что расстояние от нуля до ближайшего числа (0 - 0,5) больше, чем от этого числа к следующему (0,5 - 0,625). Это значит, что разница двух любых чисел от 0,5 до 1 даст 0, даже если эти числа не равны. Что еще хуже, в пропасть между 0,5 и 0 попадает разница чисел, больших 1. Например, «1,5-1,25=0» (см. картинку).

В «околонулевую яму» подпадает не каждая программа. Согласно статистике 70-х годов в среднем каждый компьютер сталкивался с такой проблемой один раз в месяц. Учитывая, что компьютеры приобретали массовость, разработчики «K-C-S» посчитали эту проблему достаточно серьезной, чтобы решать ее на аппаратном уровне. Предложенное ими решение состояло в следующем. Мы знаем, что при E=E min -1 (для float это «-127») и нулевой мантиссе число считается равным нулю. Если же мантисса не нулевая, то число считается не нулевым, его порядок полагается E=E min , причем неявный старший бит мантиссы полагается равным нулю. Такие числа называются денормализованными .

Строго говодя, числа с плавающей запятой теперь имеют вид:

(-1) s × 1.M × 2 E , если E min ≤E≤E max (нормализованные числа)

(-1) s × 0.M × 2 Emin , если E=E min -1. (денормализованные числа)

Вернемся к примеру. Наш E min =-1. Введем новое значение порядка, E=-2, при котором числа являются денормализованными. В результате получаем новое представление чисел:

Интервал от 0 до 0,5 заполняют денормализованные числа, что дает возможность не проваливаться в 0 рассмотренных выше примерах (0,5-0,25 и 1,5-1,25). Это сделало представление более устойчиво к ошибкам округления для чисел, близких к нулю.

Но роскошь использования денормализованного представления чисел в процессоре не дается бесплатно. Из-за того, что такие числа нужно обрабатывать по-другому во всех арифметических операциях, трудно сделать работу в такой арифметике эффективной. Это накладывает дополнительные сложности при реализации АЛУ в процессоре. И хоть денормализованные числа очень полезны, они не являются панацеей и за округлением до нуля все равно нужно следить. Поэтому эта функциональность стала камнем преткновения при разработке стандарта и встретила самое сильное сопротивление.

3.4 Очередность чисел в IEEE754
Одна из удивительных особенностей представления чисел в формате IEEE754 состоит в том, что порядок и мантисса расположены друг за другом таким образом, что вместе образуют последовательность целых чисел {n} для которых выполняется:

N

Поэтому если взять положительное число с плавающей запятой, преобразовать его к целому, прибавить «1», мы получим следующее число, которое представимо в этой арифметике. На Си это можно сделать так:

Float a=0.5; int n = *((int*) &a); float b = *((float*) &(++n)); printf("После %e следующее число: %e, разница (%e)\n", a, b, b-a);
Этот код будет работать только на архитектуре с 32-битным int.

4. Подводные камни в арифметике с плавающей запятой

Теперь – к практике. Рассмотрим особенности арифметики с плавающей запятой, к которым нужно проявить особую осторожность при программировании.
4.1 Округление
С ошибками из-за погрешностей округления в современной арифметике с плавающей запятой встретиться сложно, особенно если использовать двойную точность. Правило округления в стандарте IEEE754 говорит о том, что результат любой арифметической операции должен быть таким, как если бы он был выполнен над точными значениями и округлен до ближайшего числа, представимого в этом формате. Это требует от АЛУ дополнительных усилий и некоторые опции компилятора (такие как «-ffast-math» в gcc) могут отключить такое поведение. Особенности округления в IEEE754:
  • Округление до ближайшего в стандарте сделано не так как мы привыкли. Математически показано, что если 0,5 округлять до 1 (в большую сторону), то существует набор операций, при которых ошибка округления будет возрастать до бесконечности. Поэтому в IEEE754 применяется правило округления до четного. Так, 12,5 будет округлено до 12, а 13,5 – до 14.
  • Самая опасная операция с точки зрения округления в арифметике с плавающей запятой - это вычитание. При вычитании близких чисел значимые разряды могут потеряться, что
    может в разы увеличить относительную погрешность.
  • Для многих широко распространенных математических формул математики разработали специальную форму, которая позволяет значительно уменьшить погрешность при округлении. Например, расчет формулы «x 2 -y 2 » лучше вычислять используя формулу «(x-y)(x+y)».
4.2 Неассоциативность арифметических операций
В арифметике с плавающей запятой правило (a*b)*c = a*(b*c) не выполняется для любых арифметических операций. Например,

(10 20 +1)-10 20 =0 ≠ (10 20 -10 20)+1=1

Допустим у нас есть программа суммирования чисел.

Double s = 0.0; for (int i=0; i Некоторые компиляторы по умолчанию могут переписать код для использования нескольких АЛУ одновременно (будем считать, что n делится на 2):

Double sa, s; sa=sa=0.0; for (int i=0; i Так как операции суммирования не ассоциативны, эти две программы могут выдать различный результат.

4.3 Числовые константы
Помните, что не все десятичные числа имеют двоичное представление с плавающей запятой. Например, число «0,2» будет представлено как «0,200000003» в одинарной точности. Соответственно, «0,2 + 0,2 ≈ 0,4». Абсолютная погрешность в отдельном
случае может и не высока, но если использовать такую константу в цикле, можем получить накопленную погрешность.
4.4 Выбор минимума из двух значений
Допустим из двух значений нам нужно выбрать минимальное. В Си это можно сделать одним из следующих способов:
  1. x < y? x: y
  2. x <= y? x: y
  3. x > y? y: x
  4. x >= y? y: x
Часто компилятор считает их эквивалентными и всегда использует первый вариант, так как он выполняется за одну инструкцию процессора. Но если мы учтем ±0 и NaN, эти операции никак не эквивалентны:
x y x < y? x: y x <= y? x: y x > y? y: x x >= y? y: x
+0 -0 -0 +0 +0 -0
NaN 1 1 1 NaN NaN
4.5 Сравнение чисел
Очень распространенная ошибка при работе с float-ами возникает при проверке на равенство. Например,

Float fValue = 0.2; if (fValue == 0.2) DoStuff();
Ошибка здесь, во-первых, в том, что 0,2 не имеет точного двоичного представления, а во-вторых 0,2 – это константа двойной точности, а переменная fValue – одинарной, и никакой гарантии о поведении этого сравнения нет.

Лучший, но все равно ошибочный способ, это сравнивать разницу с допустимой абсолютной погрешностью:

If (fabs(fValue – fExpected) < 0.0001) DoStuff(); // fValue=fExpected?

Недостаток такого подхода в том, что погрешность представления числа увеличивается с ростом самого этого числа. Так, если программа ожидает «10000», то приведенное равенство не будет выполняться для ближайшего соседнего числа (10000,000977). Это особенно актуально, если в программе имеется преобразование из одинарной точности в двойную.

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

Bool AlmostEqual2sComplement(float A, float B, int maxUlps) { // maxUlps не должен быть отрицательным и не слишком большим, чтобы // NaN не был равен ни одному числу assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); int aInt = *(int*)&A; // Уберем знак в aInt, если есть, чтобы получить правильно упорядоченную последовательность if (aInt < 0) aInt = 0x80000000 - aInt; //aInt &= 0x7fffffff; //(см. комментарий пользователя Vayun) // Аналогично для bInt int bInt = *(int*)&B; if (bInt < 0) bInt = 0x80000000 - bInt; /*aInt &= 0x7fffffff;*/ unsigned int intDiff = abs(aInt - bInt); /*(см. комментарий пользователя Vayun)*/ if (intDiff <= maxUlps) return true; return false; }

В этой программе maxUlps (от Units-In-Last-Place) – это максимальное количество чисел с плавающей запятой, которое может лежать между проверяемым и ожидаемым значением. Другой смысл этой переменной – это количество двоичных разрядов (начиная с младшего) в сравниваемых числах разрешается упустить. Например, maxUlps=16, означает, что младшие 4 бита (log 2 16) могут не совпадать, а числа все равно будут считаться равными. При этом, при сравнении с числом 10000 абсолютная погрешность будет равна 0,0146, а при сравнении с 0.001, погрешность будет менее 0.00000001 (10 -8).

5. Проверка полноты поддержки IEE754

Думаете, что если процессоры полностью соответствуют стандарту IEEE754, то любая программа, использующая стандартные типы данных (такие как float/double в Си), будет выдавать один и тот же результат на разных компьютерах? Ошибаетесь. На портабельность и соответствие стандарту влияет компилятор и опции оптимизации. Уильям Кэхэн написал программу на Си (есть версия и для Фортрана), которая позволяет проверить удовлетворяет ли связка «архитектура+компилятор+опции» IEEE754. Называется она «Floating point paranoia» и ее исходные тексты доступны для скачивания . Аналогичная программа доступна для GPU . Так, например, компилятор Intel (icc) по умолчанию использует «расслабленную» модель IEEE754, и в результате не все тесты выполняются. Опция «-fp-model precise» позволяет компилировать программу с точным соответствием стандарту. В компиляторе GCC есть опция «-ffast-math», использование которой приводит к несоответствию IEEE754.

Заключение

Напоследок поучительная история. Когда я работал над тестовым проектом на GPU, у меня была последовательная и параллельная версия одной программы. Сравнив время выполнения, я был очень обрадован, так как получил ускорение в 300 раз. Но позже оказалось, что вычисления на GPU «разваливались» и обращались в NaN, а работа с ними в GPU была быстрее, чем с обычными числами. Интересно было другое - одна и та же программа на эмуляторе GPU (на CPU) выдавала корректный результат, а на самом GPU – нет. Позже оказалось, что проблема была в том, что этот GPU не поддерживал полностью стандарт IEEE754 и прямой подход не сработал.

Сейчас арифметика с плавающей запятой почти совершенна. Практически всегда наивный подход сработает, и программа, не учитывающая все ее особенности, выдаст правильный результат, а описанные подводные камни касаются только экзотических случаев. Но нужно всегда оставаться бдительным: в таком вопросе как компьютерная математика легко наступить на грабли.
! Добавить метки

Максимальное значение целого неотрицательного числа достигается в случае, когда во всех ячейках хранятся единицы. Для n-разрядного представления оно будет равно

целых неотрицательных чисел . Минимальное число соответствует восьми нулям, хранящимся в восьми битах ячейки памяти, и равно нулю. Максимальное число соответствует восьми единицам и равно

А = 1 × 2 7 + 1 × 2 6 + 1 × 2 5 + 1 × 2 4 + 1 × 2 3 + 1 × 2 2 + 1 × 2 1 + 1 × 2 0 = 1 × 2 8 - 1 = 255 10 .

Диапазон изменения целых неотрицательных чисел чисел: от 0 до 255.

Для хранения целых чисел со знаком отводится две ячейки памяти (16 битов), причем старший (левый) разряд отводится под знак числа (если число положительное, то в знаковый разряд записывается 0, если число отрицательное - 1).

Представление в компьютере положительных чисел с использованием формата "знак-величина" называется прямым кодом числа. Например, число 2002 10 = 11111010010 2 будет представлено в 16-разрядном представлении следующим образом:

0 0 0 0 0 1 1 1 1 1 0 1 0 0 1 0

Максимальное положительное число (с учетом выделения одного разряда на знак) для целых чисел со знаком в n-разрядном представлении равно:

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

Дополнительный код отрицательного числа А, хранящегося в n ячейках, равен 2 n - |A|.

Дополнительный код представляет собой дополнение модуля отрицательного числа А до 0, так как в n-разрядной компьютерной арифметике:

2 n - |А| + |А| = 0,

поскольку в компьютерной n-разрядной арифметике 2 n = 0. Действительно, двоичная запись такого числа состоит из одной единицы и n нулей, а в n-разрядную ячейку может уместиться только n младших разрядов, то есть n нулей.

Для получения дополнительного кода отрицательного числа можно использовать довольно простой алгоритм:

1. Модуль числа записать в прямом коде в n двоичных разрядах.

2. Получить обратный код числа, для этого значения всех битов инвертировать (все единицы заменить на нули и все нули заменить на единицы).

3. К полученному обратному коду прибавить единицу.

Запишем дополнительный код отрицательного числа -2002 для 16-разрядного компьютерного представления:


При n-разрядном представлении отрицательного числа А в дополнительным коде старший разряд выделяется для хранения знака числа (единицы). В остальных разрядах записывается положительное число

Чтобы число было положительным, должно выполняться условие

|А| £ 2 n-1 .

Следовательно, максимальное значение модуля числа А в га-разрядном представлении равно:

Тогда минимальное отрицательное число равно:

Определим диапазон чисел, которые могут храниться в оперативной памяти в формате длинных целых чисел со знаком (для хранения таких чисел отводится четыре ячейки памяти - 32 бита).

Максимальное положительное целое число (с учетом выделения одного разряда на знак) равно:

А = 2 31 - 1 = 2 147 483 647 10 .

Минимальное отрицательное целое число равно:

А = -2 31 = - 2 147 483 648 10 .

Достоинствами представления чисел в формате с фиксированной запятой являются простота и наглядность представления чисел, а также простота алгоритмов реализации арифметических операций.

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

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

Формат чисел с плавающей запятой базируется на экспоненциальной форме записи, в которой может быть представлено любое число. Так число А может быть представлено в виде:

A = m × q n 2.3

где m - мантисса числа;
q - основание системы счисления;
n - порядок числа.

Для единообразия представления чисел с плавающей запятой используется нормализованная форма, при которой мантисса отвечает условию:

1/n £ |m|

Это означает, что мантисса должна быть правильной дробью и иметь после запятой цифру, отличную от нуля.

Преобразуем десятичное число 555,55, записанное в естественной форме, в экспоненциальную форму с нормализованной мантиссой:

555,55 = 0,55555 × 10 3 .

Здесь нормализованная мантисса: m = 0,55555, порядок: n = 3.

Число в формате с плавающей запятой занимает в памяти компьютера 4 (число обычной точности ) или 8 байтов (число двойной точности ). При записи числа с плавающей запятой выделяются разряды для хранения знака мантиссы, знака порядка, порядка и мантиссы.

Диапазон изменения чисел определяется количеством разрядов, отведенных для хранения порядка числа, а точность (количество значащих цифр) определяется количеством разрядов, отведенных для хранения мантиссы.

Определим максимальное число и его точность для формата чисел обычной точности , если для хранения порядка и его знака отводится 8 разрядов, а для хранения мантиссы и ее знака - 24 разряда:

0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
знак и порядок знак и мантисса

Максимальное значение порядка числа составит 1111111 2 = 127 10 , и, следовательно, максимальное значение числа составит:

2 127 = 1,7014118346046923173168730371588 × 10 38 .

Максимальное значение положительной мантиссы равно:

2 23 - 1 » 2 23 = 2 (10 × 2,3) » 1000 2,3 = 10 (3 × 2,3) » 10 7 .

Таким образом максимальное значение чисел обычной точности с учетом возможной точности вычислений составит 1,701411 × 10 38 (количество значащих цифр десятичного числа в данном случае ограничено 7 разрядами).

Задания

1.26. Заполнить таблицу, записав отрицательные десятичные числа в прямом, обратном и дополнительном кодах в 16-разрядном представлении:

1.27. Определить диапазон представления целых чисел со знаком (отводится 2 байта памяти) в формате с фиксированной запятой.

1.28. Определить максимальное число и его точность для формата чисел двойной точности , если для хранения порядка и его знака отводится 11 разрядов, а для хранения мантиссы и ее знака - 53 разряда.

Назначение сервиса . Онлайн-калькулятор предназначен для представления вещественных чисел в формат с плавающей точкой.

Число

представлено в 10 2 системы счисления.
Представить число в:
нормализованном экспоненциальном виде
денормализованном экспоненциальном виде
32 битный формат IEEE 754
64 битный формат IEEE 754
Перевести обратно в десятичное представление

Правила ввода чисел

  1. Числа в десятичной системе счисления могут вводиться как без дробной, так и с дробной частью (234234.455).
  2. Числа в двоичной системе счисления состоят только из цифр 0 и 1 (10100.01).
  3. Числа в шестнадцатеричной системе счисления состоят из цифр 0 ... 9 и букв A ... F .
  4. Можно также получать обратное представление кода (из шестнадцатеричной системы счисления в десятичную, 40B00000)
Пример №1 . Представить число 133,54 в форме числа с плавающей точкой.
Решение . Представим число 133.54 в нормализованном экспоненциальном виде:
1.3354*10 2 = 1.3354*exp 10 2
Число 1.3354*exp 10 2 состоит из двух частей: мантиссы M=1.3354 и экспоненты exp 10 =2
Если мантисса находится в диапазоне 1 ≤ M Представление числа в денормализованном экспоненциальном виде .
Если мантисса находится в диапазоне 0,1 ≤ M Представим число в денормализованном экспоненциальном виде: 0.13354*exp 10 3

Пример №2 . Представить двоичное число 101.10 2 в нормализованном виде, записать в 32-битом стандарте IEEE754.
Решение .
Представление двоичного числа с плавающей точкой в экспоненциальном нормализованном виде .
Сдвинем число на 2 разрядов вправо. В результате мы получили основные составляющие экспоненциального нормализованного двоичного числа:
Мантисса M=1.011
Экспонента exp 2 =2
Преобразование двоичного нормализованного числа в 32 битный формат IEEE 754 .
Первый бит отводится для обозначения знака числа. Поскольку число положительное, то первый бит равен 0
Следующие 8 бит (с 2-го по 9-й) отведены под экспоненту.
Для определения знака экспоненты, чтобы не вводить ещё один бит знака, добавляют смещение к экспоненте в половину байта +127. Таким образом, наша экспонента: 2 + 127 = 129
Переведем экспоненту в двоичное представление.
Оставшиеся 23 бита отводят для мантиссы. У нормализованной двоичной мантиссы первый бит всегда равен 1, так как число лежит в диапазоне 1 ≤ M Для перевода целой части необходимо умножить разряд числа на соответствующую ему степень разряда.
01100000000000000000000 = 2 22 *0 + 2 21 *1 + 2 20 *1 + 2 19 *0 + 2 18 *0 + 2 17 *0 + 2 16 *0 + 2 15 *0 + 2 14 *0 + 2 13 *0 + 2 12 *0 + 2 11 *0 + 2 10 *0 + 2 9 *0 + 2 8 *0 + 2 7 *0 + 2 6 *0 + 2 5 *0 + 2 4 *0 + 2 3 *0 + 2 2 *0 + 2 1 *0 + 2 0 *0 = 0 + 2097152 + 1048576 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 = 3145728
В десятичном коде мантисса выражается числом 3145728
В результате число 101.10 представленное в IEEE 754 c одинарной точностью равно.
Переведем в шестнадцатеричное представление.
Разделим исходный код на группы по 4 разряда.
2 = 0100 0000 1011 0000 0000 0000 0000 0000 2
Получаем число:
0100 0000 1011 0000 0000 0000 0000 0000 2 = 40B00000 16



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: