Delphi大指数扩展值字符串转换错误
我试图在Delphi 7中的Win 7-64上转换一个具有大指数的扩展值,并且在我认为是有效值的情况下得到一个“无效浮点运算”异常。该值为3.6854775808e-4912,调试器报告时不会出现问题 已尝试以下例程,所有这些例程都会生成此异常: 浮动托斯特。 格式。 格式浮动。 浮动文本 有人知道发生了什么吗 编辑: 我可能应该提到,我正在搜索一个特定扩展值的缓冲区,该位置可以在缓冲区中的任何偏移处。该方法将10个字节复制到变量记录中,并从该记录中提取扩展值。然后尝试使用上述例程之一将扩展值转换为字符串,从而生成错误。我还发现,尝试将值乘以1.0也会产生错误Delphi大指数扩展值字符串转换错误,delphi,Delphi,我试图在Delphi 7中的Win 7-64上转换一个具有大指数的扩展值,并且在我认为是有效值的情况下得到一个“无效浮点运算”异常。该值为3.6854775808e-4912,调试器报告时不会出现问题 已尝试以下例程,所有这些例程都会生成此异常: 浮动托斯特。 格式。 格式浮动。 浮动文本 有人知道发生了什么吗 编辑: 我可能应该提到,我正在搜索一个特定扩展值的缓冲区,该位置可以在缓冲区中的任何偏移处。该方法将10个字节复制到变量记录中,并从该记录中提取扩展值。然后尝试使用上述例程之一将扩展值转
TDecoderRec = record
case integer of
0 : ( Binary: TBinaryArray );
1 : ( Character : TCharArray );
2 : ( ShortIntVal: ShortInt );
3 : ( ByteVal: Byte );
4 : ( SmallIntVal: SmallInt );
5 : ( WordVal: Word );
6 : ( IntegerVal: Integer );
7 : ( LongWordVal: LongWord );
8 : ( Int64Val: Int64 );
9 : ( SingleVal: Single );
10 : ( Real48Val: Real48 );
11 : ( RealVal: Real );
12 : ( DoubleVal: Double );
13 : ( CompVal: Comp );
14 : ( CurrencyVal: Currency );
15 : ( ExtendedVal: Extended );
end; { TDecoderRec }
fldExtended.AsExtended:= DecoderRec.ExtendedVal;
procedure TCustomNumericEdit.SetAsExtended( Value: Extended );
begin
AssignText( FloatToStr( Value )); { <<---- FloatToStr causes the error }
end; { TCustomNumericEdit.SetAsExtended }
这是调试器报告的值:
3.6854775808e-4882
程序项目错误;
{$APPTYPE控制台}
使用
System.SysUtils;
变量
值:扩展;
s:字符串;
开始
尝试
Value.Bytes[0]:=$74;
Value.Bytes[1]:=$02;
Value.Bytes[2]:=$08;
Value.Bytes[3]:=$03;
Value.Bytes[4]:=$54;
Value.Bytes[5]:=$6F;
Value.Bytes[6]:=$70;
Value.Bytes[7]:=$03;
Value.Bytes[8]:=$A4;
Value.Bytes[9]:=$00;
s:=FloatToStr(值);// 对该值执行的任何操作都会导致浮点异常,表明该值根本不是有效的浮点值
假设您正在搜索的值是有效的,并且唯一的问题是将该字节序列转换为浮点变量中的表示形式,那么如果您正在搜索记录缓冲区中的该特定字节序列,为什么需要转换为浮点
如果要搜索字节序列,您可能知道字节序列的字符串表示形式,因此我不明白为什么需要从已知字节序列到已知字符串表示形式的运行时转换
这就引出了一个问题,如果这个字节序列毕竟不是一个有效的扩展的值,那么您试图实现的整个基础似乎是有缺陷的,需要进一步考虑?您要转换的数字就是一个非正常数字的例子(请参见
).
所有有效的数字扩展值必须在最高尾数位置显式存储1位(这不同于single和double,其中最高位是隐含的和隐藏的,但不存储)
如果该位为零,则该数字是异常的,Wiki说:仅在8087和80287上生成。80387和更高版本将其视为无效操作数
对这些数字的操作过去依赖于编译器,例如BP7输出
?。?这一切都应该有效。我们看不到您的代码。@DelphiFan:当您从扩展
转换为字符串
,或从字符串
转换为扩展
时,是否发生错误?如果从扩展的开始,则创建字符串时这些函数中的任何一个失败都没有意义,因为内存中已经有扩展的。但是如果所表示的值太高,无法放入扩展的中,则StrToFloat()
转换肯定会失败。就像大卫说的,请显示实际失败的代码。@David和Remy:我应该说得更清楚一些,抱歉。看起来记录的ExtendedVal字段确实返回了无效的字节组合。奇怪的是,调试器没有问题,并且显示的值在可接受的范围内。为什么不显示一个简短的可编译示例来举例说明您的问题?您能像这样显示简单的代码吗?它工作正常,但它是FPC,而不是德尔福,所以我很抱歉给您带来一些不便。啊,是的,添加e:=StrToFloat(s)代码>也可以正常工作。当您反转字节时,会得到什么值。可能询问者未能从网络转换到主机字节顺序。@David:在调试器中,通过类型转换将缓冲区中的顺序颠倒并分配给扩展变量的报告为3.6854775808e+4009。。。重新扩展:=扩展(缓冲区);这听起来也不对。我认为是时候让我们停止猜测了,你应该弄清楚这10个字节到底是什么。你为什么要使用extended?@David-是的,我想到了,正如DF所说,你在调试器中得到了不同的结果(但代码中仍然是一个无效的FP-op错误),所以我认为它甚至不值得一提。但是我想知道如果不是字节顺序的话,字节的数量是否重要。为什么OP认为这是一个80位的扩展值,而不是一个单值、双值或其他扩展值(即,在一般术语中“扩展”指的是浮点类型,而不是“扩展”,具体指的是64/80位Delphi/Pascal类型),这几乎是正确的,除此之外,非规范化也没有设置此位,尽管它们是有效的扩展。但是,非规范必须有一个全零指数(即-16383)。
3.6854775808e-4882
program ProjectFloatError;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
var
Value : Extended;
s : String;
begin
try
Value.Bytes[0] := $74;
Value.Bytes[1] := $02;
Value.Bytes[2] := $08;
Value.Bytes[3] := $03;
Value.Bytes[4] := $54;
Value.Bytes[5] := $6F;
Value.Bytes[6] := $70;
Value.Bytes[7] := $03;
Value.Bytes[8] := $A4;
Value.Bytes[9] := $00;
s := FloatToStr( Value ); // <-- Invalid floating point operation
WriteLn(s);
ReadLn;
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ReadLn;
end;
end;
end.