Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как преобразовать 48-битное число? [D7, XP]


Страницы:   1 2

Zilog ©   (2006-07-04 14:30:00) 

Как преобразовать 48-битное число? При том, что мантисса кодируется 36-ю битами, а экпонента 12-ю.

например, вот это число равно еденице (1): 70368744179712
а вот это минус еденице (-1):  -140737488353281


Zilog   (2006-07-10 14:13:00) [1]

Народ, может кто-то ещё в этой теме понимает? Очень нужна ваша помощь.


SergP.   (2006-07-10 10:44:00) [2]


> x := M * Power(2, e);


А зачем Power(2,e), если Power(2,e) = 1 shl e
?


Zilog   (2006-07-10 09:43:00) [3]

MBo! Выручай, нихрена не получается у меня с этой математикой... :(


Zilog   (2006-07-07 18:01:00) [4]

MBo!

а вот это число не преобразовывается....
7FFFFF000FFF
вот на этой строчке вылетает ошибка:
x := M * Power(2, e);

не подскажешь как исправить?


Zilog   (2006-07-06 16:43:00) [5]

>>MBo ©   (06.07.06 15:24) [30]

спасибо большущее, мастер.

>>но фактическое число то же самое, а подгонять лень.

я погонял некоторые числа туда-обратно, всё с виду отлично.
но при обратной конвертации на выходе число меняется - это мне что и где надо подгонять?


MBo   (2006-07-06 15:24:00) [6]

Для отрицательных чисел-степеней двойки (-0.5, -1, -2, -4) степень смещена на единицу, но фактическое число то же самое, а подгонять лень.

procedure TForm5.Button2Click(Sender: TObject);
var
 i64, M: Int64;
 e: SmallInt;
 x, y, z, Man: Double;
begin
 try
   x := StrToFloat(Edit2.Text);
 except
   x := 0;
   Edit2.Text :='0';
 end;
 if x<>0 then
   e := Trunc(Log2(Abs(x)))
 else
   e := 0;
 M := Trunc(x * Power(2, 34 - e)) and $FFFFFFFFF;
 i64 := (M shl 12) or (e + $800);
 Edit1.Text := Format('%x',[i64]);
end;


Zilog   (2006-07-06 14:54:00) [7]

up
MBo, спасай!


Zilog   (2006-07-06 14:51:00) [8]

up
MBo, спасай!


Zilog   (2006-07-06 10:22:00) [9]

что то никак не получается сделать обратное преобразование... :(
MBo, не поможешь?...


MBo   (2006-07-05 16:57:00) [10]

>А как ты узанл, смещенная ли мантисса, и на сколько она смещена?  Т.е. откуда цифра $800
Во внутреннем формате IEEE 754 Single и Double экспонента тоже смещенная.
http://en.wikipedia.org/wiki/IEEE_floating-point_standard

А из предоставленных чисел видно - для числа 1 экспонента $800 соответствует 1, т.е. 2 в нулевой степени
мантисса $400000000  - 36 разрядов нормализуется до единицы делением на 2^36 и (почему-то) умножением на 4 = 2^2, отсюда 36-2=34
(можно рассматривать и так, что мантисса нормализована на интервал [4..8), в отличие от IEEE стандарта [1..2) )


Zilog   (2006-07-05 16:27:00) [11]

А как ты узанл, смещенная ли мантисса, и на сколько она смещена?  Т.е. откуда цифра $800.
И то же самое с нормализацией - откуда 34?

Извини, если вопросы глупые.


MBo   (2006-07-05 16:22:00) [12]

>затем - добавляем
должно быть  -
затем меняем знак


MBo   (2006-07-05 16:16:00) [13]

>А можно комментарии к алгоритму?
да вроде там все должно быть ясно...

M := i64 shr 12;
//извлекается мантисса M - 36 разрядов

if (M and $800000000) <> 0 then
  M :=  -((not M) and $FFFFFFFFF) - 1;
//если установлен старший бит - значит, число отрицательное, получаем его абсолютное значение  - для дополнительного кода это делается инверсией битов с прибавлением единицы, затем - добавляем. Если бы это было полное значение 32 или 64 разряда, этого бы не потребовалось, доп. код и так бы правильно интерпретировался

e:= (i64 and $FFF) - $800 - 34;
//выделяем младшие 12 бит, экспонента смещенная - вычитаем $800, и 34 - для нормализации мантиссы

x := M * Power(2, e);

//x :=M*2^e


Zilog   (2006-07-05 16:12:00) [14]

// получаем мантиссу и знак
 M := i64 shr 12;  
// смотрим, отрицательное ли число?
//если отрицательное, инвертируем мантиссу и убираем знак
 if (M and $800000000) <> 0 then  M :=  -((not M) and $FFFFFFFFF) - 1;
//вычисляем экспоненту (почему так - непонимаю)
 e:= (i64 and $FFF) - $800 - 34;
//эта строчка мне тоже непонятна
 x := M * Power(2, e);

2MBo: Поправь меня, если не сложно

И еще - а обратно как? из строчки вида '0.0001' как получить 48-битное число?


Zilog   (2006-07-05 15:42:00) [15]

Большое спасибо! Все вроде работает!

А можно комментарии к алгоритму? Да бы понять суть происходящего.


MBo   (2006-07-05 12:30:00) [16]

>[19]
Это не имеет отношения к самому числу, а лишь к его строковому представлению, так ты почитай про format strings - я самое простое поставил, где два знака выводится

Label1.Caption := Format('%13.8f', [x]);


Zilog   (2006-07-05 12:26:00) [17]

>>MBo ©   (05.07.06 12:18) [16]

Работает лучше. Спасибо большое.
Еджинственное:
1) часто добавляет ненужный ноль, например:
-0,10     (99999999A7FC)
-4096,10 (BFFF9999A80C)

2) Не до конца переводит число, например:
исходное -16384.0001 (BFFFFFF9780E) превращает в -16384,00


MBo   (2006-07-05 12:25:00) [18]

Верное число - 1234567890,125


Zilog   (2006-07-05 12:20:00) [19]

>>MBo ©   (05.07.06 11:23) [10]
глючит форматирование числа:
если ввести положительное число 499602D2281E, на выходе получаем '499602D22  -4   1234567890,13'.
перед форматированием числа значение показывает верное - х=1234567890,1

---

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


MBo   (2006-07-05 12:18:00) [20]

Теперь понятно, это дополнительный код.

procedure TForm5.Button1Click(Sender: TObject);
var
 i64, M: Int64;
 e: SmallInt;
 x: Double;
begin
 i64 := StrToInt64('$' + Edit1.Text);
 M := i64 shr 12;
 if (M and $800000000) <> 0 then
   M :=  -((not M) and $FFFFFFFFF) - 1;
 e:= (i64 and $FFF) - $800 - 34;
 x := M * Power(2, e);
 Label1.Caption := Format('%f',[x]);
end;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо