Внутренний формат вещественных чисел 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Внутренний формат вещественных чисел



Рассмотрим тип Single, так как он является самым коротким и, следовательно, самым простым для понимания. Остальные типы отличаются от него только количественно. В дальнейшем числа в формате Single мы будем записывать как s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm, где s означает знаковый бит, e – бит экспоненты, m – бит мантиссы. Именно в таком порядке эти биты хранятся в четырёхбайтном значении (здесь учтена перестановка байтов; напоминаю, что в процессорах Intel байты в многобайтных значениях переставляются так, что младший байт идёт первым, а старший – последним). В мантиссе хранится двоичное число. Чтобы получить истинное значение мантиссы, к ней надо мысленно добавить слева единицу с точкой (то есть, например, мантисса 1010000000000000000000 означает двоичную дробь 1.101). Таким образом, имея 23 двоичных разряда, мы записываем числа с точностью до 24-ёх двоичных разрядов. Такая запись числа называется нормализованной.

Экспонента по определению всегда целое число. Но способ записи экспоненты в вещественных числах не совпадает с обычным способом записи чисел со знаком. Ноль в этом представлении записывается как 01111111. В обычном представлении это равно 127. Соответственно, 10000000 (128 в обычном представлении) означает единицу, а 01111110 (126) означает –1, и так далее (то есть из обычного беззнакового числа надо вычесть 127, и получится число, закодированное в экспоненте).

Из описанных выше правил есть исключения. Так, если все биты экспоненты равны нулю (то есть там стоит число –127), то к мантиссе перед её началом надо добавлять не “1.”, а “0.” (денормализованная запись). Это позволяет увеличить диапазон вещественных чисел. Если бы этого исключения не было бы, минимально возможное положительное число типа Single было бы равно примерно 5.9*10-39. А так появляется возможность использовать числа до 1.4*10-45. Побочным эффектом этого является то, что числа, меньшие, чем 1.17*10-38, представляются с меньшей, чем 24 двоичных разряда, точностью.

Если все биты в экспоненте равны единице, а в матрице – нулю, то мы получаем комбинацию, известную как INF (от англ. Infinity – бесконечность). Эта комбинация используется тогда, когда результат вычислений превышает максимально допустимое форматом число. В зависимости от значения бита s бесконечность может быть положительной или отрицательной. Если же при такой экспоненте в мантиссе хоть один бит не равен нулю, такая комбинация называется NAN (Not A Number – не число). Попытки использования комбинаций NAN или INF приводят к ошибке времени выполнения.

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

Тип Double устроен точно так же, разница только в количестве разрядов и в том, какое значение экспоненты берётся за ноль. Итак, мы имеем 11 разрядов для экспоненты. За ноль берётся значение 1023.

Несколько иначе устроен Extended. Кроме количественных отличий добавляется ещё и одно качественное: в мантиссе явно указывается первый разряд. То есть, мантисса 1010... интерпретируется как 1.01, а не как 1.101, как это было в типах Single и Float. Поэтому если 23-битная мантисса типа Single обеспечивает 24-знаковую точность, а 52-битная мантисса Double – 53-битную, то 64-битная мантисса Extended обеспечивает 64-, а не 65-битную точность. Соответственно, при денормализованной форме записи первый разряд мантиссы явно содержит 0. За ноль экспоненты принимается значение 16383.

Тип Real, как уже упоминалось, стоит особняком. Во-первых, в нём используется другой порядок следования битов, а, во-вторых, не используется денормализованная форма.

«Неполноценный» Extended

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

У сопроцессора есть специальный двухбайтный регистр, называемый управляющим словом. Установка отдельных битов этого регистра диктует сопроцессору то или иное поведение. Прежде всего, это связано с тем, какие исключения может возбуждать сопроцессор. Другие биты этого регистра отвечают за то, как будут округляться числа, как сопроцессор понимает бесконечность – всё это можно при необходимости узнать из документации Intel. Нас же будут интересовать только два бита из этого слова – восьмой и девятый. Именно они определяют, как будут обрабатываться числа внутри сопроцессора.

Если восьмой бит содержит единицу (так установлено по умолчанию), то десять байт внутренних регистров сопроцессора будут использоваться полностью, и мы получим «полноценный» Extended. Если же этот бит равен нулю, то всё определяется значением бита 9. Если он равен единице, то используются только 53 разряда мантиссы (остальные всегда равны нулю). Если же этот бит равен нулю – только 24 разряда мантиссы. Это увеличивает скорость вычислений, но уменьшает точность. Другими словами, точность работы сопроцессора может быть понижена до типа Double или даже Single. Но это касается только мантиссы, экспонента в любом случае будет содержать 15 бит, так что диапазон типа Extended сохраняется в любом случае.

Для работы с управляющим словом сопроцессора в модуле System описана переменная Default8087CW:Word и процедура Set8087CW(CW:Word). При запуске программы в переменную Default8087CW записывается то управляющее слово, которое установила система при запуске программы. Функция Set8087CW записывает новое значение в управляющее слово. Одновременно это новое значение записывается в переменную Default8087CW.

Такое поведение этой функции не всегда удобно – иногда бывает нужно сохранить старое значение переменной Default8087CW (впрочем, это несложно сделать, заведя дополнительную переменную). С другой стороны, если значение управляющего слова изменить, не используя Set8087CW (а в дальнейшем мы увидим, что такие изменения могут происходить помимо нашей воли), то с помощью функции Default8087CW просто нет возможности узнать текущее значение управляющего слова. В Delphi 6 и выше появилась функция Get8087CW, позволяющая узнать значение именно контрольного слова, а не переменной Default8087CW. В более ранних версиях единственный способ получить значение этого слова – использование ассемблера, тем более что в Delphi нет проблем с ассемблерными вставками.

Установить значение управляющего слова можно с помощью команды FLDCW, прочитать – с помощью FNSTCW. Обе эти команды имеют один аргумент – переменную типа Word. Чтобы, например, установить 53-значную точность, не изменив при этом другие биты управляющего слова, надо выполнить такую последовательность команд:

asm
FNSTCW MyCW

AND MyCW,0FCFFh

OR MyCW,200h

FLDCW MyCW

end;

Современные сопроцессоры обрабатывают числа с такой скоростью, что при обычных вычислениях вряд ли может возникнуть необходимость в ускорении за счёт точности - выигрыш будет ничтожен. Эта возможность используется, в основном, в тех случаях, когда вычисления с плавающей точкой составляют значительную часть программы, а высокая точность не имеет принципиального значения (например, в движках для 3D-игр). Однако забывать об этой особенности работы сопроцессора не стоит, потому что она может преподнести неприятный сюрприз.

Пример «неправильного» поведения вещественных типов

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

На форму надо положить два компонента – метку (TLabel) и кнопку (TButton). Так как это только пример, пусть имена для этих компонентов будут Button1 и Label1. Обработчик Button1Click содержит некоторый код, результаты работы которого выводятся на форму через Label1. Таким образом, нужно запустить программу, нажать на кнопку и посмотреть, что будет написано в метке. Будем приводить только код обработчика Button1Click, так как всё остальное тривиально.

Пример 1. «Неправильное значение»

 

Итак, напишем такой код:

var R:Single; begin R:=0.1; Label1.Caption:=FloatToStr(R)end;

Что мы увидим, когда нажмём кнопку? Мы увидим «0.100000001490116». То есть расхождение в девятой значащей цифре. Ну, из справки по Delphi мы знаем, что точность типа Single – 7-8 десятичных разрядов, так что нас, по крайней мере, никто не обманывает. В чём же причина? Просто число 0.1 не представимо в виде конечной двоичной дроби, оно равно 0.0(0011). И эта бесконечная двоичная дробь обрубается на 24-ёх знаках; мы получаем не 0.1, а некоторое приближённое число (какое именно – см. выше). А если мы присвоим переменной R не 0.1, а 0.5? Тогда мы получим на экране 0.5, потому что 0.5 представляется в виде конечной двоичной дроби. Немного поэкспериментировав с различными числами, мы заметим, что точно представляются те числа, которые выражаются в виде m/2n, где m, n – некоторые целые числа (разумеется, n не должно превышать 24, а то нам не хватит точности типа Single). В качестве упражнения докажем, что любое целое число, для записи которого хватает 24-ёх двоичных разрядов, может быть точно передано типом Single.

Пример 2.

Определить, является ли палиндромом введённое с клавиатуры число.

-
+
Начало
H:=ch; Ob:=0  
N<>0
C:=n mod 10; Ob:=ob*10+c; N:=n div 10  
-
+
Ch=ob  
Ch, ‘не полиндром’
Ch, ‘- полиндром’
Конец
Ch

 

 

Program polyndrom;

uses crt;

var ch,ob,n,c:longint;

begin

clrscr; textcolor(lightgreen);

writeln ('вв-те число');

textcolor (white);

readln (ch);

n:=ch; ob:=0;

while n<>0 do

begin

c:=n mod 10;

ob:=ob*10+c;

n:=n div 10

end;

textcolor (lightred);

if ch=ob then writeln(ch,'-полиндром')

else writeln (ch,'-полиндромом не яв-ся');

readln; end.

 


2.3. Контрольные вопросы

1. Дайте определения простым, дружественным числам и числам-близнецам.

2. Что такое тройки Пифагора?

3. Какие числа называют числами Армстронга?

4. Что такое ряд Фибоначчи?

5. Для чего используется алгоритм Евклида? Как его можно реализовать?

6. Какие вещественные типы существуют в Delphi?

7. Каковы размеры типов Single, Double, Extended, Real?

8. Какая запись числа называется нормализованной?

 

Задания к лабораторной работе № 2

Теория чисел

 

Вариант 1.

1. Подсчитать количество делителей натурального числа H, формируемого датчиком случайных чисел в диапазоне от 1 до 10000.

2. Найти сумму целых положительных чисел, больших 20, меньших 100, и заканчивающихся на 2, 4 или 8.

 

Вариант 2.

1.Составить программу разложения на простые множители введенного с клавиатуры натурального числа.

2. В трехзначном числе зачеркнули первую цифру слева, когда полученное двузначное число умножили на 7, то получили исходное число. Найдите это число.

 

Вариант 3.

1.Определить, является ли простым введённое с клавиатуры натуральное число.

2.Сумма цифр двузначного числа делится на 7, само число также делится на 7. Найти все такие числа.

 

Вариант 4.

1.Разработать программу печати всех простых чисел в диапазоне от N до M (значения переменных N и M задаются с клавиатуры), а также подсчитать их количество.

2.Среди четырехзначных чисел выбрать те, у которых все четыре цифры различны.

 

Вариант 5.

1.Найти и вывести на экран 5 простых чисел, больших некоторого К, введённого с клавиатуры.

2.Найти количество четных цифр натурального числа, введенного с клавиатуры.

 

Вариант 6.

1.Дано простое число Р. Найти и вывести на экран следующее за ним простое число.

2.Найти самую большую цифру целого числа.

 

Вариант 7.

1.Дано некоторое натуральное число СН. Вывести на печать ближайшее к нему простое число.

2.Составить программу, которая подсчитывает количество палиндромов среди натуральных четырехзначных чисел

 

Вариант 8.

1. Разработать программу поиска трех простых чисел, предшествующих числу М, заданному пользователем, причем М>=10.

2.Составить программу, проверяющую, является ли заданное натуральное число совершенным.

 

Вариант 9.

1.Разработать программу поиска и печати всех чисел-близнецов, принадлежащих заданному диапазону [N,M ].

2.Проверить, являются ли два данных числа взаимно простыми.

 

Вариант 10.

1.Определить, являются ли числа, находящиеся по обе стороны от заданного чётного числа CH, близнецами.

2.Даны натуральные числа m и n. Найти такие натуральные взаимно простые p и q, что p/q = m/n.

 

Вариант 11.

1.Вычислить сумму делителей некоторого целого числа СН, формируемого генератором случайных чисел в диапазоне от 1 до 10000.

2.Найти все трехзначные числа, сумма цифр которых равна А, кратное В (А и В вводят с клавиатуры).

 

Вариант 12.

1. Найти и вынести на экран 3 совершенных числа, больших некоторого М.

2. Найти НОК (а,с).(НОК(а, с)=а*с/НОД(а,с)).

 

Вариант 13.

1.Разработать программу поиска и печати всех пар дружественных чисел, меньших 10000.

2.Среди всех четырехзначных чисел найти симметричные.

 

Вариант 14.

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

2.Вывести на экран двузначные числа, составляющие ряд Фибоначчи.

 

Вариант 15.

1.Определить разрядность натурального числа N, заданного пользователем.

2.Найти основную тройку Пифагора, в которой все числа больше некоторого А, введенного с клавиатуры



Поделиться:


Последнее изменение этой страницы: 2016-07-16; просмотров: 330; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.137.157.45 (0.045 с.)