![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как преобразовать 48-битное число? [D7, XP]
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;