Quadratwurzelverfahren
-
Hallo leute
ich bin heute über ein Verfahren gestolpert was ich nicht ganz verstehe.
es geht um quadratwurzeln, bzw um eine verfahren sie zu errechnen(in der spiele programmierung)...
// wurzel.cpp inline float FastWurzelExact(float r) //ist klar { unsigned long *ptr = NULL; //ein zeiger auf ein unsigned if(r == 0.0f) return 0.0f; //um unnötiges zu vermeiden if(r < 0.0f) r = -r; float Value = r; //das ist ein startwert float halfValue = 0.5f*r; //zweiter wert (wegen heron algorithmus) ptr = (unsigned long*)&r; // was heisst das? *ptr=(0xbe6f0000-*ptr)>>1; // und das? float temp1Wurzel = r; temp1Wurzel *= 1.5f-temp1Wurzel*temp1Wurzel*halfValue; temp1Wurzel *= 1.5f-temp1Wurzel*temp1Wurzel*halfValue; return Value*temp1Wurzel; //rest ist wieder klar }also das ist eine mischung aus dem heron algorithmus und einem trick auf die interne speicherung von gleitkommazahlen zuzugreifen
aber wie geht das? mit dieser hexzahl (ist übrigens 3194945536 im dezimal system)???
und was heisst (unsigned*)&r ???mfg mosho
-
Zunächst zur binären Darstellung von Gleitkommazahlen:
http://de.wikipedia.org/wiki/Gleitkommazahl#IEEE_754_und_andere_NormenDie Zeile
ptr = (unsigned long*)&r;weist dem long-Zeiger die Adresse der Float-Zahl r zu; über den Zeiger kann man nun die Gleitkommazahl als Integerzahl behandeln.
Hier
*ptr=(0xbe6f0000-*ptr)>>1;wird der als Integerzahl interpretierte Wert der Gleitkommazahl von 0xBE6F0000 abgezogen und um ein Bit nach rechts verschoben. Warum auch immer.
Wie das nun genau funktioniert, kannst du hier nachlesen.
Achja, und noch ein Tip: benutze am besten einfach std::sqrt() aus <cmath>. So etwas lohnt sich meist nicht, da viel zu plattformabhängig, fehleranfällig etc.
-
ja aber es ist viel schneller
und es geht um spiele programmieren...
naja danke ichw erd mir das mal angucken
-
Skym0sh0 schrieb:
ja aber es ist viel schneller
und es geht um spiele programmieren...
naja danke ichw erd mir das mal angucken
Glaubst du, dass die Typen, die diese Funktionen implementiet haben sich nix dabei geadacht haben?! Und das du das besser machen kannst, als ein erfahrener Programmierer?!
Und glaub mir.. In der Spieleprogrammierung hast du ganz andere Flaschenhälse, als ein paar sqrt ...
-
ach quatsch ich will nicht ein besseres verfahren schreiben sodnern das eifnach nur verstehen...
wobei ich hab den source code von quake 3
und da gibts auch so ein wurzelverfahren, aber das funktioniert nicht annähernd so gut wie das hier(wurzel 9 -> quake: 0.345432)
(wurzel 9 -> das hier: 2.999999)
-
Skym0sh0 schrieb:
wobei ich hab den source code von quake 3
und da gibts auch so ein wurzelverfahren, aber das funktioniert nicht annähernd so gut wie das hierDas funktioniert ganz gut, du hast bloß nicht verstanden, dass dabei gar nicht die Wurzel berechnet wird.
-
MFK schrieb:
Skym0sh0 schrieb:
wobei ich hab den source code von quake 3
und da gibts auch so ein wurzelverfahren, aber das funktioniert nicht annähernd so gut wie das hierDas funktioniert ganz gut, du hast bloß nicht verstanden, dass dabei gar nicht die Wurzel berechnet wird.
Fast Inverse Squareroot.
Übrigens, ich hab das mal aus Interesse "gebencht". Mittlerweile ist der Geschwindigkeitsvorteil nicht mehr so nennenswert wie vielleicht zu Pentium MMX Zeiten (soll heißen, es lohnt sich nicht).
-
naja ich hab mir auch mal so einen benchmark geshcrieben
bis zu eienr millionen wurzeln pro sekudne ist alles ok
aber alles dadrüber braucht sqrt aus 'math.h' oder 'cmath' einige sekunden
10.000.000 wurzeln in knapp 20 oder 30 sekunden vom normalen sqrt errechnet
mit meinem vorgestellten geht das ganze in knapp 1 sekunde
und die näherung sit auch gutwie gesagt wurzel 9 ist 2.99999...