2010-12-03 10 views
7

Comment puis-je calculer la racine carrée d'un Float en C#, similaire à Core.Sqrt dans XNA?Comment calculer la racine carrée d'un flotteur en C#

+1

Utilisez la magie puissante - [0x5f3759df] (http://www.codemaestro.com/reviews/9) – jball

+0

que la magie est la racine carrée inverse. Mais une magie similaire existe pour sqrt. Et cela perd de la précision. – CodesInChaos

+0

@CodeInChaos - le deuxième exemple de code dans l'article a une implémentation pour sqrt: * "Notez que la seule vraie différence est dans la valeur de retour - au lieu de renvoyer y, renvoyez le nombre * y comme racine carrée" * – jball

Répondre

15

Calculez-le pour double, puis repoussez pour flotter. Peut être un peu lent, mais devrait fonctionner.

(float)Math.Sqrt(inputFloat) 
+0

ne lâchez pas la précision? – Chris

+0

J'ai toujours espéré que, d'une certaine façon, .Net l'optimiserait pour être une opération entièrement flottante (toutes les 32 bits) dans les coulisses. Est-ce que quelqu'un sait si cela est optimisé? – Detmar

+0

@Chris, la précision sera la même que l'entrée. Le calcul est fait en utilisant des doubles. –

0
var result = Math.Sqrt((double)value); 
+1

float et double calculer différemment non? – Chris

+2

@Chris - La méthode Math.Sqrt prend un double et renvoie un double. C'est pourquoi j'ai casté le paramètre en double. –

+0

Je vois ça. Mais je parle de chars. Merci quand même – Chris

4

Je déteste dire cela, mais 0x5f3759df semble prendre 3x aussi longtemps que Math.sqrt. Je viens de faire quelques tests avec des minuteurs. Math.Sqrt dans une boucle d'accès à des matrices précalculées a abouti à environ 80ms. 0x5f3759df dans les mêmes circonstances a abouti à 180 + ms

Le test a été effectué plusieurs fois en utilisant les optimisations de mode de libération.

Source ci-dessous:

/* 
    ================ 
    SquareRootFloat 
    ================ 
    */ 
    unsafe static void SquareRootFloat(ref float number, out float result) 
    { 
     long i; 
     float x, y; 
     const float f = 1.5F; 

     x = number * 0.5F; 
     y = number; 
     i = *(long*)&y; 
     i = 0x5f3759df - (i >> 1); 
     y = *(float*)&i; 
     y = y * (f - (x * y * y)); 
     y = y * (f - (x * y * y)); 
     result = number * y; 
    } 

    /* 
    ================ 
    SquareRootFloat 
    ================ 
    */ 
    unsafe static float SquareRootFloat(float number) 
    { 
     long i; 
     float x, y; 
     const float f = 1.5F; 

     x = number * 0.5F; 
     y = number; 
     i = *(long*)&y; 
     i = 0x5f3759df - (i >> 1); 
     y = *(float*)&i; 
     y = y * (f - (x * y * y)); 
     y = y * (f - (x * y * y)); 
     return number * y; 
    } 

    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     int Cycles = 10000000; 
     Random rnd = new Random(); 
     float[] Values = new float[Cycles]; 
     for (int i = 0; i < Cycles; i++) 
      Values[i] = (float)(rnd.NextDouble() * 10000.0); 

     TimeSpan SqrtTime; 

     float[] Results = new float[Cycles]; 

     DateTime Start = DateTime.Now; 

     for (int i = 0; i < Cycles; i++) 
     { 
      SquareRootFloat(ref Values[i], out Results[i]); 
      //Results[i] = (float)Math.Sqrt((float)Values[i]); 
      //Results[i] = SquareRootFloat(Values[i]); 
     } 

     DateTime End = DateTime.Now; 

     SqrtTime = End - Start; 

     Console.WriteLine("Sqrt was " + SqrtTime.TotalMilliseconds.ToString() + " long"); 
     Console.ReadKey(); 
    } 
} 
+3

Pour être honnête, cela semble assez hors-sujet, mais c'est quand même intéressant! – Tara

+1

http://stackoverflow.com/questions/268853/is-it-possible-to-write-quakes-fast-invsqrt-function-in-c? –

-3
private double operand1; 

private void squareRoot_Click(object sender, EventArgs e) 
{ 
    operand1 = Math.Sqrt(operand1); 
    this.textBox1.Text = operand1.ToString(); 
} 
+2

Bienvenue dans Stack Overflow! Bien que cette réponse soit probablement correcte et utile, il est préférable que vous [incluiez quelques explications avec elle] (http://meta.stackexchange.com/q/114762/159034) pour expliquer comment cela aide à résoudre le problème. Cela devient particulièrement utile à l'avenir, s'il y a un changement (peut-être non apparenté) qui le fait cesser de fonctionner et les utilisateurs ont besoin de comprendre comment il a déjà fonctionné. –

Questions connexes