请更正delphi中二进制形式的浮点数(类型:double)的这些功能
Pls correct these functions of float number (type: double) under binary form in delphi
我写了 2 个函数来转换浮点数 into/from 二进制,但结果不正确。请帮我找出它的错误。 (我找到了一些关于这个主题的常见问题解答,但它们是为 C/C++ 编写的)
function MyFloatToBin(d: double): String;
var
d_ptr: ^Int64;
d_str: string;
i: Integer;
ch: char;
begin
d_ptr:= @d;
d_str:= '';
for i:= 0 to 63 do begin
if (d_ptr^ and (1 shl i)) > 0 then
ch:= '1'
else
ch:= '0';
d_str:= d_str + ch;
end;
Result:= 'F' + d_str;
end;
function MyBinToFloat: Double;
var
d_str: String;
i64: Int64;
d_ptr: ^double;
i, len: Integer;
begin
d_str:= pop;
len:= length(d_str);
if (pos('F', d_str) <> 1)and(len <> 65) then begin
push(d_str);
exit;
end;
i64:= 0;
for i:= 2 to len do
if d_str[i] = '1' then
i64:= i64 or (1 shl (i - 2));
d_ptr:= @i64;
Result:= d_ptr^;
end;
正在使用
temp: string;
f: double;
temp:= MyFloatToBin(pi);//pi = 3.14....
f:= MyBinToFloat(temp);//result at f is 0
我想知道变量 f 应该是 3.14...但是..???
请帮我改正它们。
谢谢
你的问题本质上是掩码计算。你做 1 shl I
给出了一个 32 位的值。您必须执行 UInt64(1) shl I
以获得 64 位值。
这是您修复的代码:
function MyFloatToBinString(d: double): String;
var
VP : ^UInt64;
I : Integer;
begin
VP := @d;
Result := 'F';
for I := 63 downto 0 do begin
if (VP^ and (UInt64(1) shl I)) <> 0 then
Result := Result + '1'
else
Result := Result + '0';
end;
end;
function MyBinStringToFlat(S : String) : Double;
var
V : UInt64;
I : Integer;
J : Integer;
begin
if (Length(S) <> 65) or ((S[1] <> 'F') and (S[1] <> 'f')) then
raise Exception.Create('Invalid format');
V := 0;
for I := 65 downto 2 do begin
case S[I] of
'1': V := V or (UInt64(1) shl (65 - I));
'0': { Nothing to do };
else
raise Exception.Create('Invalid format');
end;
end;
Result := PDouble(@V)^;
end;
如果你想测试:
procedure TForm1.Button1Click(Sender: TObject);
var
V1 : Double;
V2 : Double;
S : String;
begin
V1 := 3.1416;
Memo1.Lines.Add(IntToHex(PUInt64(@V1)^));
S := MyFloatToBinString(V1);
Memo1.Lines.Add(S);
V2 := MyBinStringToFlat(S);
Memo1.Lines.Add(V2.ToString);
end;
我写了 2 个函数来转换浮点数 into/from 二进制,但结果不正确。请帮我找出它的错误。 (我找到了一些关于这个主题的常见问题解答,但它们是为 C/C++ 编写的)
function MyFloatToBin(d: double): String;
var
d_ptr: ^Int64;
d_str: string;
i: Integer;
ch: char;
begin
d_ptr:= @d;
d_str:= '';
for i:= 0 to 63 do begin
if (d_ptr^ and (1 shl i)) > 0 then
ch:= '1'
else
ch:= '0';
d_str:= d_str + ch;
end;
Result:= 'F' + d_str;
end;
function MyBinToFloat: Double;
var
d_str: String;
i64: Int64;
d_ptr: ^double;
i, len: Integer;
begin
d_str:= pop;
len:= length(d_str);
if (pos('F', d_str) <> 1)and(len <> 65) then begin
push(d_str);
exit;
end;
i64:= 0;
for i:= 2 to len do
if d_str[i] = '1' then
i64:= i64 or (1 shl (i - 2));
d_ptr:= @i64;
Result:= d_ptr^;
end;
正在使用
temp: string;
f: double;
temp:= MyFloatToBin(pi);//pi = 3.14....
f:= MyBinToFloat(temp);//result at f is 0
我想知道变量 f 应该是 3.14...但是..??? 请帮我改正它们。 谢谢
你的问题本质上是掩码计算。你做 1 shl I
给出了一个 32 位的值。您必须执行 UInt64(1) shl I
以获得 64 位值。
这是您修复的代码:
function MyFloatToBinString(d: double): String;
var
VP : ^UInt64;
I : Integer;
begin
VP := @d;
Result := 'F';
for I := 63 downto 0 do begin
if (VP^ and (UInt64(1) shl I)) <> 0 then
Result := Result + '1'
else
Result := Result + '0';
end;
end;
function MyBinStringToFlat(S : String) : Double;
var
V : UInt64;
I : Integer;
J : Integer;
begin
if (Length(S) <> 65) or ((S[1] <> 'F') and (S[1] <> 'f')) then
raise Exception.Create('Invalid format');
V := 0;
for I := 65 downto 2 do begin
case S[I] of
'1': V := V or (UInt64(1) shl (65 - I));
'0': { Nothing to do };
else
raise Exception.Create('Invalid format');
end;
end;
Result := PDouble(@V)^;
end;
如果你想测试:
procedure TForm1.Button1Click(Sender: TObject);
var
V1 : Double;
V2 : Double;
S : String;
begin
V1 := 3.1416;
Memo1.Lines.Add(IntToHex(PUInt64(@V1)^));
S := MyFloatToBinString(V1);
Memo1.Lines.Add(S);
V2 := MyBinStringToFlat(S);
Memo1.Lines.Add(V2.ToString);
end;