delphi 为什么此代码会导致“浮点操作无效”错误?

jdzmm42g  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(274)

当执行下面的代码时,它应该使用当前高度计算到地平线的距离,但它只能计算到63米高,然后从64米高开始执行“无效浮点运算”。
为什么会出现此错误?

unit Unit_ch4_2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  r:real;
begin
  r := SQRT(SQR(6350000 + StrToint(Edit1.Text)) - SQR(6350000));
  Edit2.Text := FloatToStr(r / 1000);
end;

end.
uidvcgyl

uidvcgyl1#

您的代码中使用的数据类型太小,无法分别容纳较大的中间值。通过调用SQRStrToInt, Delphi 对此处使用的中间数据类型的假设是错误的!
当您通过定义一个更大的数据类型(如Int64)并使用StrToInt64来明确告诉编译器使用该类型的常量时,代码现在可以正确运行,输入的值最大为99 999 999 999!

procedure TForm1.Button1Click(Sender: TObject);
const
  v: int64 = 6350000;
var
  r: real;
  a: int64;
begin
  Edit2.Clear;
  a := SQR(v + StrToInt64(Edit1.Text)); // this line can give a negative result when the parameter passed to SQR is too big
  r := SQRT(a - SQR(v)); // negative parameter of SQRT causes an error!
  Edit2.Text := FloatToStr(r / 1000);
end;

在上面的代码中,我使用了一个额外的行来存储一个额外的局部变量中的intermedia值,以显示计算的哪一部分导致了错误。如果SQR的参数太大(即使使用了Int64),a中的结果是一个负数。这将导致调用SQRT时出错!
下面是一个代码版本,其简短格式与您使用的相同:

procedure TForm1.Button1Click(Sender: TObject);
const
  v: int64 = 6350000;
var
  r: real;
begin
  Edit2.Clear;
  r := SQRT(SQR(v + StrToInt64(Edit1.Text)) - SQR(v));
  Edit2.Text := FloatToStr(r / 1000);
end;

相关问题