【问题标题】:how x87 precision affects square roots?x87 精度如何影响平方根?
【发布时间】:2014-05-31 00:31:24
【问题描述】:

我编写了一些代码来测试 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 使用 24 位精度作为 sqrt 精度,另一个使用 64 位精度。正如预期的那样,24 位版本的速度要快很多(10-20% 取决于输入)。

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

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

这是怎么回事?

【问题讨论】:

  • 为什么你会得到错误的结果?
  • 因为我的输入高达31位,虽然24位精度会考虑到这一点,但看起来只有最终结果受精度影响。
  • 24位精度表示32位用于存储值,24位用于尾数,8位用于指数
  • 有道理。如果您想回答 only 操作结果受 x87 控制字中精度设置的影响,并且该来源可以是任何大小,我会接受它作为答案。
  • 如果将单/浮点精度计为 24 位,那么 long doube 或 80 位类型只有 64 位精度

标签: assembly x86 x87


【解决方案1】:

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

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

考虑到数据以 80 位双扩展精度浮点数的形式始终存储在 FPU 中。 FILD 和 FIST 不要根据精度“忘记”位。精度的作用是在结果足够精确时中止计算,并在之后取消适当的位。

英特尔® 64 和 IA-32 架构软件开发人员手册卷。 1 第8.1.5.2章(精度控制领域):

使用这些设置会抵消双重的优势 扩展精度浮点格式的 64 位有效数字长度。 当指定降低精度时,有效数的四舍五入 value 将右侧未使用的位清零。

所以FSQRT 在完整的 80 位寄存器上工作,并以 24 位的精度中止。我怀疑它会以 25 的精度中止以获得重要的舍入值。然后结果的“冗余” 60 位将被取消。你得到了一个 24 位的结果,这对于 16 位整数来说已经足够了,正如你注意到的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 2020-05-25
    相关资源
    最近更新 更多