StrToFloat 谁错了:Delphi 或 ASE/SQL 服务器
StrToFloat and who is wrong: Delphi or ASE/SQL Server
最近发现一件奇怪的事:
的结果
var
d: double;
begin
d := StrToFloat('-1.79E308');
与 ASE 和 SQL 服务器通过
转换为浮点字段类型的字符串值 '-1.79E308' 不同
INSERT INTO my_table (my_float_field) VALUES (-1.79E308)
对于 Delphi 内存转储是 9A BB AD 58 F1 DC EF FF
对于 ASE/SQL select 上数据包中的服务器值是 99 BB AD 58 F1 DC EF FF
。
谁错了,都是服务器还是Delphi?
我们工作的前提是 StrToFloat
产生最接近提供的十进制值的可表示二进制浮点值。
您提供的两个十六进制值是相邻的。您可以看到它们在尾数中相差 1
。下面是一些 Python 解码两个值的代码:
>>> import struct
>>> struct.unpack('!d', 'ffefdcf158adbb9a'.decode('hex'))[0]
-1.7900000000000002e+308
>>> struct.unpack('!d', 'ffefdcf158adbb99'.decode('hex'))[0]
-1.79e+308
请记住,Python 使用最短的有效值打印浮点值,最接近的可表示值是实际值。 ffefdcf158adbb99
解码为 Python 眼中打印为 -1.79e+308
的值,足以证明 ffefdcf158adbb99
是最接近的可表示值。换句话说,Delphi 代码给出了错误的答案。
并且,出于好奇,在相反的方向:
>>> hex(struct.unpack('<Q', struct.pack('<d', float('-1.79e308')))[0])
'0xffefdcf158adbb99L'
有趣的是,32 位 Delphi 编译器生成 ffefdcf158adbb99
,而 64 位 Delphi 编译器生成 ffefdcf158adbb9a
。这是一个明显的缺陷,应作为错误报告提交给 Quality Portal。
最近发现一件奇怪的事:
的结果var
d: double;
begin
d := StrToFloat('-1.79E308');
与 ASE 和 SQL 服务器通过
转换为浮点字段类型的字符串值 '-1.79E308' 不同INSERT INTO my_table (my_float_field) VALUES (-1.79E308)
对于 Delphi 内存转储是 9A BB AD 58 F1 DC EF FF
对于 ASE/SQL select 上数据包中的服务器值是 99 BB AD 58 F1 DC EF FF
。
谁错了,都是服务器还是Delphi?
我们工作的前提是 StrToFloat
产生最接近提供的十进制值的可表示二进制浮点值。
您提供的两个十六进制值是相邻的。您可以看到它们在尾数中相差 1
。下面是一些 Python 解码两个值的代码:
>>> import struct >>> struct.unpack('!d', 'ffefdcf158adbb9a'.decode('hex'))[0] -1.7900000000000002e+308 >>> struct.unpack('!d', 'ffefdcf158adbb99'.decode('hex'))[0] -1.79e+308
请记住,Python 使用最短的有效值打印浮点值,最接近的可表示值是实际值。 ffefdcf158adbb99
解码为 Python 眼中打印为 -1.79e+308
的值,足以证明 ffefdcf158adbb99
是最接近的可表示值。换句话说,Delphi 代码给出了错误的答案。
并且,出于好奇,在相反的方向:
>>> hex(struct.unpack('<Q', struct.pack('<d', float('-1.79e308')))[0]) '0xffefdcf158adbb99L'
有趣的是,32 位 Delphi 编译器生成 ffefdcf158adbb99
,而 64 位 Delphi 编译器生成 ffefdcf158adbb9a
。这是一个明显的缺陷,应作为错误报告提交给 Quality Portal。