【发布时间】: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 位精度