Betragsberechnung eines Vectors in C
====================================
Guten Abend!!
Hab mal eine kleine Frage.
Ich möchte in C den Betrag eines 3D Vectors berechnen, über phythagoras.
Betrag(bzw Länge) x = Wurzel aus der Summe der Quadrate.
Nun muss man ja gezwungenermassen mit potenzen rechnen, bzw mit
funktionen die diese berechnen. (sqrt/pow)
Kann man das nicht irgendwie umgehen? normalerweise sagt man ja X^2 =
x*x oder pow(x, 2) oder sqr(x)
ich würde gerne auf die bibliotheksfunktionen komplett verzichten.
das quadrat am liebsten so x = x^2; (ich weiß der "^" ist eigentlich der
Xor op) und ebenso die quadratwurzel mit x = x^(1/2) (werde ich vorher
noch mit 1000 multiplizieren, da ich die berechnung in int durchführen
möchte.)
momentan sieht die berechnung so aus:
Micha S. schrieb:> kann ich die sqrt() funktion irgendwie umgehen?
Was machst du denn mit dem Betzrag.
Wenn du die nur vergleichen willst, brauchst du die Wurzel nicht ziehen.
schon klar :) naja eig. würde es mit ein paar tricks auch so gehen,
danach den wert skalieren und gut. ich werte einen beschleunigungssensor
aus, der betrag ist die resultierende kraft (im stand die erdanz.)
genau, und um zu wissen ob es stimmt müsste ich den befehlssatz von
meinem kleinen lernen (zu faul...:)
aber ichg werde es mal bei gelegenheit einbinden und testen (wobei mir
da schon mal beim durchschauen push & pop fehlen)
Sehr schön, danke. hab mir sowas ähnliches gestern bereits selber
geschrieben:
1
ui16int_sqrt(ui32zahl)
2
{
3
ui16wurzel=UI16MAX;
4
ui16temp=wurzel-1;
5
while(temp<wurzel)
6
{
7
wurzel=temp;
8
temp=wurzel+zahl/wurzel>>1;
9
}
10
returnwurzel;
11
}
funktioniert sehr gut, aber wie man auf den ersten blick sieht werden
die nachkommastellen nicht berücksichtigt, die funktion eignet sich
somit mehr für größere zahlen. lt. der funktion ist:
wurzel 4 = wurzel aus 5...8, nämlich 2.
man könnte sie, wenn nötig natürlich noch mit dem modulo erweitern...
Um die Auflösung zu erhöhen eignet sich die Fixed-Point-Arithmetic,
dabei verschiebst du quasi das Komma um ein bestimmtes Vielfaches von
zwei und erhälts so Nachkommastellen. Ein Vielfaches von 2 deshalb, weil
es sich mit Bit-Shift-Operationen realisieren lässt.
Viel Erfolg!
DirkB schrieb:> Micha S. schrieb:>> kann ich die sqrt() funktion irgendwie umgehen?>> Was machst du denn mit dem Betzrag.> Wenn du die nur vergleichen willst, brauchst du die Wurzel nicht ziehen.
Ich würde auch lieber diese Variante nehmen.
Karl Heinz Buchegger schrieb:> Ralf's Version dürfte grob geschätzt um mindstens den Faktor 20 bis 30> schneller sein als deine Newton Iteration.
Guten morgen, na heute besser gelaunt? ;-)
Ja das ist klar, das ist abhängig von der zahl, je größer desto mehr
durchläufe & somit langsamer. Mir ging es ja, wie gestern erwähnt,
hauptsächlich darum die fliesskommaarithmetik zu umgehen, was mir auch
erst mal gelungen ist. nächstes kriterium war dann der Speicherbedarf,
deswegen die entscheidung zur Newtonschen Iteration.
Micha S. schrieb:> erst mal gelungen ist. nächstes kriterium war dann der Speicherbedarf,> deswegen die entscheidung zur Newtonschen Iteration.
Gut.
Das ist jetzt in Ralfs Code noch nicht optimal gelöst. sIdx muss keine
32 Bit Variable sein und ob die anderen beiden 32 BIt sein müssen,
müsste man analysieren. Auch der Return Datentyp muss kein 32 Bit Typ
sein, 16 Bit reichen. Aber abgesehen von den paar Bytes auf dem Stack
trägt sein Code auch höchst wahrscheinlich weniger auf, als die Division
in deinem Code, die das eigentliche Übel darstellt. AVR können nur
schlecht allgemein dividieren. Von daher ist so gut wie jeder Code, der
keine derartige Division braucht immer besser. Und von der Länge des
C-Codes in Source Form solltest du dich nicht blenden lassen
Karl Heinz Buchegger schrieb:> Das ist jetzt in Ralfs Code noch nicht optimal gelöst. sIdx muss keine>> 32 Bit Variable sein und ob die anderen beiden 32 BIt sein müssen,>> müsste man analysieren. Auch der Return Datentyp muss kein 32 Bit Typ>> sein, 16 Bit reichen.
Was ich bei meinem Code noch dazu sagen muss ist, dass ich den Code auf
einem STM32 laufen habe. Aus diesem Grund sind meine Variablen 32Bit
breit damit ich mir irgendwelche Extension Befehle im Assembler sparen
kann.
Bei einer Umsetzung auf einem AVR sollte man, wie Karl Heinz schon
geschrieben hat, die Datenformate noch ein wenig für den AVR anpassen.
Gruß,
Ralf