【发布时间】:2017-01-21 22:54:06
【问题描述】:
通读3D游戏编程大师的技巧,我发现了这个用内联汇编编写的排序函数:
inline float FastSqrt(float Value)
{
float Result;
_asm
{
mov eax, Value
sub eax, 0x3F800000
sar eax, 1
add eax, 0x3F800000
mov Result, eax
}
return(Result);
}
这是实际平方根的近似值,但准确度足以满足我的需要。
这实际上是如何工作的?这个神奇的0x3F800000 值是什么?我们如何通过减法、旋转和加法获得平方根?
这是它在 C/C++ 代码中的样子:
inline float FastSqrt_C(float Value)
{
float Result;
long Magic = *((long *)&Value);
Magic -= 0x3F800000;
Magic >>= 1;
Magic += 0x3F800000;
Result = *((float *)&Magic);
return(Result);
}
【问题讨论】:
-
0x3F800000 是 1.0 的 32 位浮点表示
-
有趣,这就是为什么当我将参数 Value 更改为 int 时我猜我会得到不正确的结果?看起来这个函数只适用于浮点数?
-
更重要的是,这是指数偏差。所以它消除了偏差,将指数减半,然后将偏差加回去。它也与尾数有点混淆。
-
@vexe 所涉及的一般原理可以看this question
标签: assembly optimization x86 square-root sar