wurzel ziehen nicht möglich - Freescale

OP #748445
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
Angehängte Dateien:
Gast
__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);
}
OP
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?
Gast
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.
OP
> 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"
Gast
@   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.
OP
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
Persönliche Seite
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.
OP
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
Gast
@  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?

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.