19

この非常に素晴らしいページを確認すると、次のようになります。

http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi

次のプログラムが表示されます。

#define SQRT_MAGIC_F 0x5f3759df 
 float  sqrt2(const float x)
{
  const float xhalf = 0.5f*x;

  union // get bits for floating value
  {
    float x;
    int i;
  } u;
  u.x = x;
  u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0
  return x*u.x*(1.5f - xhalf*u.x*u.x);// Newton step, repeating increases accuracy 
}

私の質問は次のとおりです。これが次のように実装されていない特定の理由はありますか:

#define SQRT_MAGIC_F 0x5f3759df 
 float  sqrt2(const float x)
{

  union // get bits for floating value
  {
    float x;
    int i;
  } u;
  u.x = x;
  u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0

  const float xux = x*u.x;

  return xux*(1.5f - .5f*xux*u.x);// Newton step, repeating increases accuracy 
}

分解すると、1つMUL少なくなります。出演したことに何か目的はありますxhalfか?

4

1 に答える 1

4

80 ビット レジスタを使用する従来の浮動小数点演算は、80 ビット レジスタに保持される中間結果として乗算器が最後の行で一緒にリンクされている場合により正確である可能性があります。

上位の実装での最初の乗算は、それに続く整数演算と並行して行われ、異なる実行リソースを使用します。一方、2 番目の関数はより高速に見えますが、実際に上記の理由があるかどうかを判断するのは困難です。また、const float xux = x*ux; ステートメントは、結果を 32 ビット浮動小数点数に戻します。これにより、全体的な精度が低下する可能性があります。

これらの関数を直接テストして、math.h のsqrt関数と比較できます(float ではなく double を使用)。このようにして、どちらがより速く、どちらがより正確であるかを確認できます。

于 2013-11-23T18:50:46.770 に答える