我试图在Win 7-64上的Delphi 7中转换具有大指数的扩展值,并在我认为是有效值的地方收到“无效浮点运算”异常。值为3.6854775808e-4912,调试器将毫无问题地报告该值。
尝试了以下例程,并且所有例程都会生成此异常:
FloatToStr。
格式。
FormatFloat。
FloatToText。
有人知道发生了什么吗?
编辑:
我可能应该提到我正在缓冲区中搜索特定的扩展值,并且该位置可以在缓冲区中的任何偏移处。该方法将10个字节复制到变体记录,并从记录中提取扩展值。然后尝试使用上述例程之一将扩展值转换为字符串,这会产生错误。我还发现尝试将值乘以1.0也会产生错误。
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 }
这些是包含ExtendedVal的十六进制字节:
74 02 08 03 54 6F 70 03 A4 00
这是调试器报告的值:
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.
最佳答案
您要转换的数字是非正常数字的示例(请参阅
https://en.wikipedia.org/wiki/Extended_precision#x86_Extended_Precision_Format)。
所有有效的数字扩展值都必须在最高尾数位置显式存储1位(这不同于单和双精度,其中隐含和隐藏了最高位,但未存储)。
Wiki说,如果该位为零,则该数字是不正常的:仅在8087和80287上生成。80387及更高版本将其视为无效的操作数。
这些数字上的运算以前是依赖于编译器的,例如BP7输出?.?<000000000000E-4882
,但是任何32岁以上的Delphi都会引发异常。