![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Преобразование чисел
bestolkov © (2011-07-20 18:15:00)Всем здравствуйте! Существует ли остроумный способ преобразования числа из формата с плавающей точкой в фиксированную точку без потери точности?
MBo (2011-07-21 14:39:00) [1]Вот как схематично выглядит расположение на положительной числовой оси чисел с фиксированной и с плавающей запятой:
http://mbo88.narod.ru/Image2.gif
Преобразование без потерь возможно на участках, где фикс. идут чаще.
Например, если числа с фикс. точкой с восемью двоичными цифрами после запятой, то однозначное преобразование возможно для Double > 2^44.
Если нужно для любых - безумный путь в [3]
bestolkov (2011-07-21 14:11:00) [2]Ну, ключевое слово в вопросе - без потерь..
Барт (2011-07-21 13:31:00) [3]> Это ясно, а чем код лучше приведенного?
Остроумнее
RWolf (2011-07-21 13:10:00) [4]
> Существует ли остроумный способ преобразования числа из
> формата с плавающей точкой в фиксированную точку без потери
> точности?
есть такой способ.
inline int float2int( double d ) {
union Cast { double d; long l; };
volatile Cast c;
cd = d + 6755399441055744.0;
return cl;
}
bestolkov (2011-07-21 12:23:00) [5]
> MBo © (21.07.11 11:43) [9]
Это ясно, а чем код лучше приведенного?
MBo (2011-07-21 11:43:00) [6]Из числа с плавающей точкой выделяется мантисса и экспонента, и формируется число с фиксированной точкой в формате знак - 15 бит целой части - 16 бит дробной siiiiiii.ffffff
bestolkov (2011-07-21 10:34:00) [7]MBo © (21.07.11 10:06) [7]
Не совсем понял Вас, прокомментируйте ответ,пожалуйста
MBo (2011-07-21 10:06:00) [8]Неуий маразм для чисел, по модулю меньших 32767, без учета денормализованных и т.п.
Для крупных чисел больше значащих цифр сохраняется
var
d, d2: Double;
i64, m64, ex: Int64;
ifixed_s_15_16: Integer;
begin
Randomize;
d := (Random - 0.5) * exp(Random * 10);
Memo1.Lines.Add(FloatToStr(d));
i64 := PInt64(@d)^;
m64 := i64 and $000FFFFFFFC00000;
m64 := m64 or $0010000000000000;
ex := i64 shr 52;
ex := ex and 2047;
ex := ex - 1023;
if ex < 0 then
m64 := m64 shr (-ex)
else
m64 := m64 shl ex;
m64:= m64 shr 36;
ifixed_s_15_16 := m64;
if i64 < 0 then
ifixed_s_15_16 := - ifixed_s_15_16;
d2 := ifixed_s_15_16 / 65536;
Memo1.Lines.Add(FloatToStr(d2));
bestolkov (2011-07-21 07:55:00) [9]
> MBo © (20.07.11 20:31) [1]
function f2lx(Real_value: Double ; const scale: real; bits: integer): lfix;
var value : Double ;
begin
value:= Real_value / scale * LX_Range;
if (value < 0) then
begin
value := value-0.5;
if (value < -LX_Range) then Result:= $80000000 else Result :=Round(value) and LMask[bits];
end
else
begin
value :=value+ 0.5;
if (value > LX_MAX) then Result:=$7FFFFFFF else Result:= Round(value) and LMask[bits];
end;
end;
MBo (2011-07-21 07:03:00) [10]>хватит и меньше,
Это уже будет некое перекодирование
Полвторого (2011-07-21 02:40:00) [11]
> MBo © (20.07.11 21:30) [3]
хватит и меньше, если учесть что на большом удалении от нуля между отдельными числами с плавающей точкой возникают дырки кое-где и больше единицы.
MBo (2011-07-20 21:30:00) [12]>Без потери точности по определению нельзя
Ну как же, всего (1 + 64 + 32768)=32833-битовое число понадобится для Extended ;)
Anatoly Podgoretsky (2011-07-20 21:16:00) [13]Без потери точности по определению нельзя
MBo (2011-07-20 20:31:00) [14]Приведите пример неостроумного преобразования, чтобы убедиться, что мы думаем об одних и тех же сущностях