Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Генерация программы вычисления целой части плавающего числа




Функцию y = floor(x), вычисляющую наименьшее целое, не превосходящее вещественного аргумента x, можно определить спецификацией:

formula flp(real x, int y) = y <= x & x < y + 1;

floor(real x: int y) post flp(x, y);

Требуется построить быстрый алгоритм вычисления floor для чисел в плавающем формате, который определяется стандартом IEEE 754-2008. Плавающее число представляется тройкой (S, E, T), где S = {0, 1} – знак числа, E – сдвинутая экспонента, а T – мантисса в нормализованном представлении без старшего разряда (равного 1). Значение числа определяется по формуле:

z = (-1)S * 2E-bias * (1 + 21-p * T).

Здесь bias – сдвиг экспоненты, p – число битов в представлении мантиссы, 1 £ E £ 2w - 2, w – число битов в представлении экспоненты. Значения E = 0 и E = 2w - 1 предназначены для кодирования нулей и специальных значений. Значения констант для формата 32 (float): bias = 127, w = 8 и p = 24; для формата 64 (double): bias = 1023, w = 11 и p = 53. Данные константы определим в программе описаниями:

const nat bias;

const subtype (nat i: i >= 2) w; // w >= 2;

const subtype (nat i: i > 0) p; // p > 0;

const nat m = p + w;

// число битов в представлении чисел x и y.

Здесь m – число битов в представлении плавающего числа. Определим типы для S, E и T:

type bit = { nat a | a = 0 or a = 1};

type nate = { nat e | 1 <= e & e <= 2^w - 2};

type natp = { nat i | i < 2^(p-1)};

type intm = { int i | - 2^(m-1) <= i & i < 2^(m-1)};

Результат y должен иметь тип intm той же разрядности, что и аргумент x. Например, типу float должен соответствовать int32. Определим спецификацию функции floor:

formula val(bit S, nate E, natp T: real) =

(-1)^S * 2^(E - bias) * (1 + 2^(1-p) * T);

formula Floor(bit S, nate E, natp T, intm y) =

flp(val(S, E, T), y);

floor(bit S, nate E, natp T: intm y)

post Floor(S, E, T, y);

Необходимо доказать тотальность спецификации, то есть лемму:

Floor_total: lemma exists intm y. Floor(S, E, T, y).

Оказывается, доказать эту лемму невозможно. Причина в том, что для больших E значение y, удовлетворяющее предикату Floor, может выйти за пределы типа intm. Например, для формата m = 32 результат y может не поместиться даже в формате 64. Значение функции val ограничено по модулю значением 2^(E – bias+1), поскольку 1 + 2^(1-p) * T < 2. Отсюда следует правильное определение типа nate, для которого лемма Floor_total доказуема:

type nate = { nat e | 1 <= e & e < bias + m - 2};

Введем функцию val1:

formula val1(bit S, int d, nat z: real) =

(-1)^S * 2^d * z;

Тогда val(S, E, T) = va1(S, E – bias – p + 1, 2^(p-1) + T). Вычисление функции floor можно свести к вычислению функции floor1 со спецификацией:

formula P_fl1(int d, nat z) =

z >= 2^(p-1) & z < 2^p & d < w;

formula Floor1(bit S, int d, nat z, intm y) =

flp(val1(S, d, z), y);

floor1(bit S, int d, nat z: intm y)

pre P_fl1(d, z) post Floor1(S, d, z, y);

Сначала следует доказать тотальность спецификации floor1, а именно - лемму:

Floor1_total: lemma P_fl1(d, z) Þ exists intm y. Floor1(S, d, z, y).

Сведение floor к floor1 реализуется доказательством леммы:

Floor_fb1: lemma Floor(S, E, T, y) & d=E – bias – p + 1 & z = 2^(p-1) + T ÞP_fl1(d, z) & Floor1(S, d, z, y)

По лемме генерируется следующее определение предиката floor:

floor(bit S, nate E, natp T: intm y)

{ floor1(S, E – bias – p + 1, 2^(p-1) + T: y) }

post Floor(S, E, T, y);

Алгоритм для floor1 реализуется разбором случаев на базе леммы

Floor1_def: lemma P_fl1(d, z) & Floor1(S, d, z, y) Þ

(S = 0)? ((d >= 0)? y = 2^d * z:

y = div(z, 2^(-d))):

(d >= 0)? y = - 2^d * z:

(mod(z, 2^(-d)) = 0)?

y = - div(z, 2^(-d)):

y = - div(z, 2^(-d)) – 1

Здесь div – деление нацело, а mod – деление по модулю. Программа для floor1 генерируется по лемме очевидным образом. Следует отметить, что результат вычисления y = 2^d * z (и y = - 2^d * z) может оказаться неточным, если неточным было исходное представление числа в плавающем формате. Погрешность может достигать до 2^d.

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

· 2^(p-1) + T на 2^(p-1) or T;

· z * 2^d на z << d;

· div(z, 2^(-d)) на z >> (-d);

· mod(z, 2^(-d)) = 0 на (z & (2^(-d) – 1)) = 0.

Значение 2^(-d) – 1 состоит из (-d) единичных битов. Такое значение можно сгенерировать посредством сдвига: (2^p – 1) >> (p + d). Корректность указанных замен обеспечивается доказательством следующих лемм:

plus_eq: lemma T < 2^(p-1) Þ 2^(p-1) + T = 2^(p-1) or T;sh_left: lemma d >= 0 & d < p Þ z * 2^d = z << d;sh_right: lemma g > 0 & g < p Þ div(z, 2^g) = z >> g;mod_eq: lemma g > 0 & mod(z, 2^g) = 0 Þ (z & (2^g – 1)) = 0;sh_mask: lemma g > 0 & g < p Þ 2^g – 1 = (2^p – 1) >> (p - g);

С учетом указанных замен следует модифицировать лемму Floor1_def и получить по ней новую версию программы floor1. Далее тело floor1 подставляется на место вызова в floor. Приведем окончательную программу, дополненную вычислением floor для нулевого аргумента, но не допускающую других специальных значений в качестве аргумента:

 


floor(bit S, nate E, natp T: intm y)

{ int d = E – bias – p + 1; nat z = 2^(p-1) or T;

if (E = 0 & T = 0) y = 0[6]

else if (S = 0)

{ if (d >= 0) y = z <<d else

if (–d >= p) y = 0 else y = z>>(-d) }

else if (d >= 0) y = - (z << d)

else if (–d >= p) y = - 1

else if ((z & ((2^p – 1) >> (p + d))) = 0)

y = - (z >> (-d))

else y = - (z >> (-d)) – 1

};




Поделиться с друзьями:


Дата добавления: 2015-06-27; Просмотров: 468; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.008 сек.