我试图在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都会引发异常。

10-08 17:02