2010-12-03 12 views
7

Wie kann ich die Quadratwurzel von Float in C#, ähnlich Core.Sqrt in XNA berechnen?So berechnen Sie die Quadratwurzel eines Float in C#

+1

Verwendung mächtige Magie - [0x5f3759df] (http://www.codemaestro.com/reviews/9) – jball

+0

Das Magie ist die inverse Quadratwurzel. Aber ähnliche Magie existiert für sqrt. Und das verliert Präzision. – CodesInChaos

+0

@CodeInChaos - das zweite Codebeispiel im Artikel hat eine Implementierung für sqrt: * "Beachten Sie, dass der einzige wirkliche Unterschied im Rückgabewert liegt - anstatt y zurückzugeben, geben Sie die Zahl * y als Quadratwurzel an" * – jball

Antwort

15

Berechnen Sie es für double und dann zurück in float. Kann ein bisschen langsam sein, sollte aber funktionieren.

(float)Math.Sqrt(inputFloat) 
+0

wont es lose Präzision? – Chris

+0

Ich habe immer gehofft, dass irgendwie .Net dies optimieren würde, um ein All-Float (alle 32-Bit) Betrieb hinter den Kulissen zu sein. Weiß jemand, ob dies optimiert wird? – Detmar

+0

@Chris, die Genauigkeit wird die gleiche wie die Eingabe sein. Die Berechnung erfolgt mit Doppelpunkten. –

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

float und double anders berechnen nein? – Chris

+2

@Chris - Die Math.Sqrt-Methode nimmt ein Double und gibt ein Double zurück. Deshalb habe ich den Parameter als Double gecastet. –

+0

Ich sehe das. Aber ich spreche von Schwimmern. Danke trotzdem – Chris

4

Hass, dies zu sagen, aber 0x5f3759df scheint 3x solange Math.Sqrt zu nehmen. Ich habe gerade ein paar Tests mit Timern gemacht. Math.Sqrt in einer For-Schleife Zugriff auf vorberechnete Arrays ergab ca. 80ms. 0x5f3759df unter den gleichen Bedingungen ergab 180 + ms

Der Test wurde mehrmals mit dem Release-Modus Optimierungen durchgeführt.

Quelle unter:

/* 
    ================ 
    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

Um ehrlich zu sein, das scheint ziemlich unorthodox, aber trotzdem interessant! – 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

Willkommen bei Stack Overflow! Während diese Antwort wahrscheinlich richtig und nützlich ist, ist es vorzuziehen, wenn Sie [http://meta.stackexchange.com/q/114762/159034] erklären, wie es hilft, das Problem zu lösen. Dies wird besonders nützlich in der Zukunft, wenn es eine (möglicherweise nicht zusammenhängende) Änderung gibt, die dazu führt, dass es nicht mehr funktioniert und die Benutzer verstehen müssen, wie es einmal funktioniert hat. –