Delphi有isqrt吗?

Sti*_*ers 2 delphi math

我正在对UInt64值中的大整数进行一些繁重的工作,并且想知道Delphi是否具有整数平方根函数.现在我正在使用,Trunc(Sqrt(x*1.0))但我想必须有一个更高效的方式,也许有一个内联汇编程序的片段?(Sqrt(x)x:UInt64抛出D7无效类型编译器错误,因此*1.0位.)

And*_*and 10

我离集会专家很远,所以这个答案只是我鬼混.

但是,这似乎有效:

function isqrt(const X: Extended): integer;
asm
  fld X
  fsqrt
  fistp @Result
  fwait
end;
Run Code Online (Sandbox Code Playgroud)

只要在调用之前将FPU控制字的舍入设置设置为"截断"即可isqrt.最简单的方法可能是定义辅助函数

function SetupRoundModeForSqrti: word;
begin
  result := Get8087CW;
  Set8087CW(result or $600);
end;
Run Code Online (Sandbox Code Playgroud)

然后你就可以做到

procedure TForm1.FormCreate(Sender: TObject);
var
  oldCW: word;
begin
  oldCW := SetupRoundModeForSqrti; // setup CW
  // Compute a few million integer square roots using isqrt here
  Set8087CW(oldCW); // restore CW
end;
Run Code Online (Sandbox Code Playgroud)

测试

这真的能提高性能吗?好吧,我测试了

procedure TForm1.FormCreate(Sender: TObject);
var
  oldCW: word;
  p1, p2: Int64;
  i: Integer;
  s1, s2: string;
const
  N = 10000000;
begin
  oldCW := SetupRoundModeForSqrti;

  QueryPerformanceCounter(p1);
  for i := 0 to N do
    Tag := isqrt(i);
  QueryPerformanceCounter(p2);
  s1 := inttostr(p2-p1);

  QueryPerformanceCounter(p1);
  for i := 0 to N do
    Tag := trunc(Sqrt(i));
  QueryPerformanceCounter(p2);
  s2 := inttostr(p2-p1);

  Set8087CW(oldCW);

  ShowMessage(s1 + #13#10 + s2);
end;
Run Code Online (Sandbox Code Playgroud)

并得到了结果

371802
371774.
Run Code Online (Sandbox Code Playgroud)

因此,它根本不值得.天真的方法trunc(sqrt(x))更易于阅读和维护,具有出色的未来和向后兼容性,并且不易出错.

  • @Worm:我们并不真正关心downvote,如果你解释其背后的原因以便每个人都可以学习,那就更有价值了.毕竟,这就是SO的全部意义所在. (2认同)