- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
通读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
的表示。虽然这是事实,但它与计算方式无关。要理解它,您需要知道非负 float 是如何存储的。 f = (1+m)*2^x
,与 0 <= m < 1
和m
作为尾数,x
指数。另请注意 x
是带有偏差存储的,所以二进制文件中的实际内容是 x+127
。 32 位值由符号位(在我们的例子中为零)和随后存储 x+127
的 8 位指数组成。最后是 23 位尾数,m
。 (请参阅wikipedia article)。
应用一些基本数学,
sqrt(f) = sqrt((1+m)*2^x)
= sqrt(1+m)*sqrt(2^x)
= sqrt(1+m)*2^(x/2)
因此,作为一个粗略的近似,我们需要将指数减半,但由于偏差,我们不能仅仅这样做 x/2
我们需要(x-127)/2 + 127
。这个127
移位到适当的位位置就是神奇的 0x3f800000
.
除以 2 是通过右移一位来实现的。由于这对整个 float 进行操作,因此它也会对尾数产生副作用。
首先,假设原始指数是偶数。那么移出的最低有效位为零。因此,尾数也减半,所以我们最终得到的是:sqrt(f) = (1+m/2)*2^(x/2)
。我们得到的指数是正确的,但尾数是 (1+m/2)
而不是sqrt(1+m)
。最大相对误差为 (1.5 - sqrt(2))/sqrt(2) ~ 6%
如果 m
就会发生这种情况差不多1
含义f
接近,但小于 2
的奇次幂。以f=7.99
为例。该公式为我们提供了大约 2.998
而不是2.827
确实有错误 6%
.
现在,如果指数是奇数,则最低有效位将为 1
当移入尾数时,会导致增加一半。因此,我们得到sqrt(f) = (1.5+m/2)*2^((x-1)/2)
。最大错误实际上是当 m=0
时,这将是 (1.5/sqrt(2)-sqrt(1))/sqrt(1)
这又是在 6%
附近。对于上面接近 2 的奇数次方的数字,会发生这种情况。
这两种情况相结合意味着,如果输入值恰好接近 2 的奇数次方,最差的误差约为 6%。对于 2 的偶次幂,结果是准确的。
关于assembly - 这个 sqrt 近似内联汇编函数如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41785416/
我在玩(美丽的)多项式 x^4 - 10x^2 + 1 . 看看会发生什么: In[46]:= f[x_] := x^4 - 10x^2 + 1 a = Sqrt[2];
对于整个参数范围 x,a >= 0,是否有一种优雅的数值稳定评估以下表达式的方法? f(x,a) = sqrt(x+a) - sqrt(x) 还有没有提供这种功能的任何编程语言或库?如果是,以什么名义
我正在制作自定义运算符 (≠,≈,Σ,√),平方根的实现很有趣。我写的 prefix func √ (item:Double) -> Double { return sqrt(item) }
这是我每秒调用多次的函数: static inline double calculate_scale(double n) { //n may be int or double return s
我对 C++ 很陌生,我有这段代码,代码如下所示: D = (sum_B / double(E))*std::sqrt(E) 有人可以将其解释为数学公式或易于理解的东西吗,我不确定这是什么 std::
这个问题在这里已经有了答案: Can a declaration affect the std namespace? (2 个答案) Why doesn't adding sqrt() cause
考虑以下代码: #include #include const int COUNT = 100000000; int main() { double sum = 0; for (i
x**(1/2)、math.sqrt() 和 cmath.sqrt() 有什么区别? 为什么 cmath.sqrt() 单独得到二次项的复根?我应该专门将它用于我的平方根吗?他们在后台做了什么不同的事
我创建了一个小程序,如下: #include #include #include int main(int argc, char *argv[]) { int i;
我得到了如下表达式(Sqrt[XXX] 的数量未知) Sqrt[A+B] + Sqrt[Min[A,B]] * Min[Sqrt[C],D] 我想把所有的 Sqrt[XXX] 变成 Sqrt(XXX)
这次重复: T(n) = sqrt(n) * T(sqrt(n)) + n 它似乎无法用 Master 定理求解。它似乎也无法用 Akra-Bazzi 解决。即使我设置 n = 2^k 以便 T(2^
在数学中,恒等式 (1 + sqrt(2))^2 = 3 + 2*sqrt(2) 成立。但在浮点(IEEE 754,使用单精度,即 32 位)计算中,情况并非如此,因为 sqrt(2) 没有精确的二进
我创建了一个小程序,如下: #include #include #include int main(int argc, char *argv[]) { int i;
这给了我 0: int B=-4; double A = Math.Sqrt(1/B); 但是这个 NaN double A = Math.Sqrt(-4); 第一次计算怎么可能不失败或者至少不返回
template T sqrt (T); template complex sqrt(complex); double sqrt(double); void f(complex z) { sq
这里是 Python 的新手。我试图了解此函数如何检查素数: from itertools import count, islice from math import sqrt def is_prim
上述复杂性的大 O 表示法是什么? 是不是O(n) 最佳答案 是的。关键是日志里面的平方根没有区别: O(sqrt(n) log(sqrt(n))) = O(sqrt(n) 1/2 log(n)) =
如果 g(n) = sqrt(n)sqrt(n),g(n) = O(2n) 的复杂度是多少? 感谢任何帮助。 最佳答案 比较两个指数函数时,一个有用的技巧是让它们具有相同的基数: √n√n = (2l
我正在查看我的代码,希望提高它的性能,然后我看到了这个: int sqrt = (int) Math.floor(Math.sqrt(n)); 哦,好的,我真的不需要调用 Math.floor,因为转
我试图找到满足子句 (x - y * √ 2016)/(y + √ 2016) = 2016 的数字。数字 x 和 y 可以是有理数。 这是我已经尝试过的: #include #include #
我是一名优秀的程序员,十分优秀!