x87精度如何影响平方根?

马拉杜

我写了一些代码来测试fsqrt函数,结果对我来说并不完全有意义。这是代码(在delphi中):

uses
 mmsystem;

var
 rand:longint=123456789;

function rng:longint;
asm
 imul eax,[rand],$08088405
 inc eax
 mov [rand],eax
end;

function int_sqrt(adata:longint):longint;
asm
 fnstcw word([esp-2])

// mov word([esp-4]),$1f3f  // 80bit precision
 mov word([esp-4]),$1c3f  // 24bit precision
 fldcw word([esp-4])

 mov [esp-8],eax
 fild longint([esp-8])

 fsqrt

 fistp longint([esp-8])
 mov eax,[esp-8]

 fldcw word([esp-2])
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 start,i,r,s1,s2:longint;
 time0,time1:longint;
begin
 timebeginperiod(1);
 time0:=timegettime;

 start:=1000000000;
 for i:=(start+0) to (start+100000000) do begin
  //r:=i;
  r:=abs(rng);
//  r:=2134567890;
//  r:=$7fffffff;
  s1:=int_sqrt(r);
  s2:=trunc(sqrt(r));
  if s1<>s2 then
   showmessage('error: '+inttostr(r)+'/'+inttostr(s1)+'/'+inttostr(s2));
 end;

 time1:=timegettime;
 timeendperiod(1);
 showmessage('Milliseconds: '+inttostr(time1-time0));
end;

很简单,我正在寻找一个整数的平方根。在int_sqrt中,精度行之一使x87的sqrt精度使用24位精度,其他64位精度。如预期的那样,24位版本的速度要快得多(10-20%取决于输入)。

这是问题所在。我还没有找到使用32位精度时会返回错误结果的单个32位(实际上是31位,最后一位是未使用的符号)!

到目前为止,我唯一的理论是仅最终结果取决于精度,而不取决于源或任何中间缓冲区。这将是有道理的,因为31位int的平方根的最大结果大小为16位。

那是怎么回事吗?

kh

英特尔®64和IA-32体系结构软件开发人员手册,第1卷。2A第3-291页(FILD):

将带符号整数的源操作数转换为双精度扩展浮点格式,并将该值压入FPU寄存器堆栈。源操作数可以是一个字,双字或四字整数。加载时没有舍入错误。

考虑到数据始终以80位双精度扩展浮点数存储在FPU中FILD和FIST不会根据精度“忘记”位。的精度的影响是中止计算当结果是足够精确,并且以消除相应位之后

英特尔®64和IA-32体系结构软件开发人员手册,第1卷。1第8.1.5.2章(精确控制字段):

使用这些设置会使双重扩展精度浮点格式的64位有效长度的优点无效。当指定降低的精度时,有效值的舍入会将右边的未使用位清除为零。

因此,它FSQRT适用于完整的80位寄存器,并以24位精度终止。我怀疑它会以25的精度中止以获得较大的取整值。然后,结果的“冗余” 60位将被无效。您得到了24位结果,这足以满足您注意到正确的16位整数的要求。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

TOP 榜单

热门标签

归档