Hallo, ich programmiere einen Freescale Mikrocontroller und brauche für meine Rechung eine Wurzel-Funktion. Habe in Library nichts finden können :-( Im Anhang sieht man die Funktion, die berechnet werden soll. Für "quadratische Zahlen" (wurzel(25)=5, wurzel(16)=4,...) existiert eine Library-Funktion aber damit kann ich nicht anfangen. Was kann ich machen? Gibt es andere Möglichkeiten um Wurzel zu ziehen, bzw. Wurzel umgehen? Oder weiß jemand ob man es vielleicht doch bei Freescale-Mikrocontroller realisieren kann? Danke ps. obwohl ich math.h includiere, kann ich die sqrt()-Funktion nicht benutzen. Der Compiler meckert dass es kein Prototyp existiert
__inline int JSqrt(float number) { long i; float x2, y; const float threehalfs = 1.5f; x2 = number * 0.5f; y = number; i = * (long *) &y; // evil floating point bit level hacking i = 0x5f3759df - (i >> 1); // what the fugg? y = * (float *) &i; y = y * (threehalfs - (x2 y y)); // 1st iteration //y = y * ( threehalfs - ( x2 y y ) ); // 2nd iteration, this can be removed return (int) (1/y); }
Hallo Jankey, danke für die Antwort. Kannst du auch etwas dazu sagen? Was macht die Funktion genau? was macht das:
1 | i = * (long *) &y; // evil floating point bit level hacking |
2 | i = 0x5f3759df - (i >> 1); // what the fugg? |
3 | y = * (float *) &i; |
4 | y = y * (threehalfs - (x2 y y)); |
warum wird int zurückgegeben?
Slm also ich kenne mich mit Freescale uC nicht aus und in C habe ich auch noch nie programiert aber wenn der math.h exp(x) und ln(x) unterstützt kannst du die n-te wurzel aus x so ziehen: x^1/n=exp(ln(x)/n)
Gast wrote: > Slm > > also ich kenne mich mit Freescale uC nicht aus und in C habe ich auch > noch nie programiert aber wenn der math.h exp(x) und ln(x) unterstützt > kannst du die n-te wurzel aus x so ziehen: > > x^1/n=exp(ln(x)/n) Wobei es eigentlich keinen wirklichen Grund gibt, warum eine Implementierung zwar keine Wurzel aber ln und exp unterstützen sollte. sqrt kann man mit einer Newton Iteration ziemlich einfach berechnen. Dazu braucht man lediglich Gleitkommaoperationen Addition, Multiplikation und Division. > ps. obwohl ich math.h includiere, kann ich die sqrt()-Funktion nicht > benutzen. Der Compiler meckert dass es kein Prototyp existiert Kannst du das mal näher ausführen
1 | #include <math.h> |
2 | |
3 | int main() |
4 | {
|
5 | double x, y; |
6 | |
7 | x = 28.3; |
8 | y = sqrt( x ); |
9 | }
|
sollte ohne Probleme und ohne Fehler compilieren.
Jupps... Wurzeln ziehen kann man auch iterativ, aber Du hast doch eine C-Library, oder nicht?
> sqrt kann man mit einer Newton Iteration ziemlich einfach > berechnen. Dazu braucht man lediglich Gleitkommaoperationen > Addition, Multiplikation und Division. oje es ist lange her, dass wir bei der Wurzel-Herleitung in der Schule mit Addition, Multiplikation und Division gearbeitet haben. Ich kann micht garnicht mehr daran erinnern, wie wir es gamacht haben :-( >> ps. obwohl ich math.h includiere, kann ich die sqrt()-Funktion nicht >> benutzen. Der Compiler meckert dass es kein Prototyp existiert > Kannst du das mal näher ausführen naja wie gesagt, wenn ich versuche zu debuggen und mein Code compiliere, wird mir Linker-Fehler angezeigt. Ich vermute die math.h-Header besitzt die Funktion garnicht, daher die Fehlermeldung. > >
1 | > #include <math.h> |
2 | >
|
3 | > int main() |
4 | > { |
5 | > double x, y; |
6 | >
|
7 | > x = 28.3; |
8 | > y = sqrt( x ); |
9 | > } |
10 | >
|
> > sollte ohne Probleme und ohne Fehler compilieren. nicht unter CodeWarrior. Nach dem ausführen kommt Fehlermeldung "kein Prototyp der Funktion sqrt() vorhanden"
Hast Du math.h includiert? Nachtrag: Um Quadratwurzel von a zu berechnet, iteriere gemaesz:
Michael G. wrote: > Jupps... Wurzeln ziehen kann man auch iterativ, aber Du hast doch eine > C-Library, oder nicht? ich vermute eine unvollständige C-Library.
Michael G. wrote:
> Hast Du math.h includiert?
math.h ist includiert
Ok siehe oben... ;) Du brauchst uebrigens garnicht soviele Schritte, das konvergiert recht schnell. Kommt drauf an wieviele sichere Stellen Du brauchst.
@ Karl heinz Buchegger (kbuchegg) >Wobei es eigentlich keinen wirklichen Grund gibt, warum >eine Implementierung zwar keine Wurzel aber ln und exp >unterstützen sollte. wie gesagt habe nch nie in C programmiert. ich denke das QUADRAT WURZEL also sqrt(x) in fast jeder Programmiersprache in irgend einer Form existiert aber er hat ja nach der N-te Wurzel gefragt und das gibt es icht immer als Standart. > sqrt kann man mit einer Newton Iteration ziemlich einfach > berechnen. Dazu braucht man lediglich Gleitkommaoperationen > Addition, Multiplikation und Division. da hast du recht, wusste aber niht mehr wie das ging.
Michael G. wrote: > Ok siehe oben... ;) Du brauchst uebrigens garnicht soviele Schritte, das > konvergiert recht schnell. Kommt drauf an wieviele sichere Stellen Du > brauchst. naja 2-3 Nachkommestellen reichen völlig aus
Naja die k-te Wurzel kannste auch berechnen, indem Du das Newton-Verfahren mit
anwendest.
das n-te Wurzel brauche ich nicht, ich will nur das Quadrat-Wurzel. o man das ist ja super, dann wäre damit mein Problem geklärt :-D >Um Quadratwurzel von a zu berechnet, iteriere gemaesz: >x_{n+1}=\frac{x_n + \frac{a}{x_n}}{2} nach wievielen Schritten bekommt man 2-3 richtige Nachkommastellen?
@ Gast (Gast) >also sqrt(x) in fast jeder Programmiersprache in irgend einer Form >existiert aber er hat ja nach der N-te Wurzel gefragt und das gibt es >icht immer als Standart. Aber AFAIK gibt es eine allgemeine Potenzfunktion pow(x,y) welche
berechnet. Und wer in Mathematik nicht nur Kreide holen war, weiss
sprich pow(x, 1/y); MfG Falk
OK, also fuer 3 Nachkommastellen duerften 4 Iterationen ausreichen, das Verfahren konvergiert quadratisch. Ich gebe Dir mal ein Beispiel. Wenn Du z.B.
berechnen willst:
und
Du kannst natuerlich komplett numerisch Rechnen, also nicht mit rationalen Zahlen wie in diesem Beispiel. Solltest eventuell noch achten dass Du Dir keine Ausloeschungsprobleme einfaengst dabei. Das ergebnis
verwendet immer
, also das Ergebnis der vorherigen Iteration, siehe oben. Falls Du eine allgemeine Potenzfunktion hast geht es natuerlich auch so. Dann liegt es aber nahe dass Du die Wurzelfunktion auch zur Verfuegung hast.
1 | #include <stdio.h> |
2 | #include <math.h> |
3 | |
4 | double MySqrt( double a ) |
5 | {
|
6 | double Xn = a / 2.0; |
7 | double Xnn = 0.0; |
8 | |
9 | while( fabs( Xn - Xnn ) > 0.01 ) { |
10 | Xnn = Xn; |
11 | Xn = Xn / 2.0 + a / ( 2 * Xn ); |
12 | }
|
13 | |
14 | return Xn; |
15 | }
|
16 | |
17 | int main() |
18 | {
|
19 | double y = MySqrt( 26.0 ); |
20 | |
21 | printf( "%lf %lf\n", y, y*y ); |
22 | }
|
Wenn du den Aufwand mit der While Schleife nicht brauchst, sollte es (je nach Zahlenbereich von a) ausreichen einfach double MySqrt( double a ) { double Xn = a / 2.0; Xn = Xn / 2.0 + a / ( 2 * Xn ); Xn = Xn / 2.0 + a / ( 2 * Xn ); return Xn; } Wenn das nicht reicht, dann iterierst du ganz einfach noch mal :-) Xn = Xn / 2.0 + a / ( 2 * Xn ); Xn = Xn / 2.0 + a / ( 2 * Xn ); Xn = Xn / 2.0 + a / ( 2 * Xn ); Und wenn das dann immer noch nicht reicht, dann halt noch ein 4.tes mal: Xn = Xn / 2.0 + a / ( 2 * Xn ); Xn = Xn / 2.0 + a / ( 2 * Xn ); Xn = Xn / 2.0 + a / ( 2 * Xn ); Xn = Xn / 2.0 + a / ( 2 * Xn ); Du kannst beliebig oft iterieren, jedesmal wird das Ergebnis genauer.
Waow das ist klasse, super vielen Dank. Habt vielen dank für eure Hilfe. Ps. jetzt kann ich mich wieder an die Schulzeit erinnern :-). Genau so haben wir es die Wurzel-Funktion hergeleitet und für das n-te Wurzel gab es mehrere Möglichkeiten. Einer von den war das Newton-Verfahren Nochmals Dankeschön
@ Falk Brunner (falk) >Aber AFAIK gibt es eine allgemeine Potenzfunktion pow(x,y) welche siehe oben: >also ich kenne mich mit Freescale uC nicht aus und in C habe ich auch noch nie programiert noch mal siehe oben: >wie gesagt habe nch nie in C programmiert. aus beiden aussagen kann man herleiten das ich nicht wissen kann ob einer power in C implementiert ist. >Und wer in Mathematik nicht nur Kreide holen war, siehe oben: >x^1/n=exp(ln(x)/n) ist das nicht das selbe pow(x,1/n)=x^1/n?
Bidde bidde... das Wurzelziehen auf die Art nennt sich uebrigens Heronverfahren, ist aber nur ein Spezialfall des Newton-Verfahrens. Gruss, Michael
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.