wurzel ziehen nicht möglich - Freescale

#748445
Lesenswert?

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 #748528
Lesenswert?

__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);
}
#748564
Lesenswert?

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 #748716
Lesenswert?

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)
#748727
Lesenswert?

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.
#748749
Lesenswert?

> 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 #748779
Lesenswert?

@   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.
#748793
Lesenswert?

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?
#748802
Lesenswert?

@ 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 #748807
Lesenswert?

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.
#748820
Lesenswert?

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.
#748822
Lesenswert?

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 #748827
Lesenswert?

@  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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren