www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wurzel ziehen asm


Autor: juergen klauck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi !
ich moechte (muss)messwerte auswerten.
hab max, min und mittelwert geschaft, brauche aber noch ne
standardabweichung (sigma) fuer die ich aber ne wurzel ziehen muss
(quadratwurzel)das ganze in asm.
hat jemand ne funktion oder ein tut wo ich das lernen kann??
gruss juergen

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du könntest das doch in C programmieren und dann sehen, wie der Compiler
das umsetzt.

Autor: juergen klauck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gute idee besten dank!
hab das schon in c++ gemacht.
 muesste nur den compieler sagen, dass er mir das in einer
einigermassen verstaendlichen art ausgibt jemand ne idee ??

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das sind mir schon die richtigen Assemblerprogrammierer :-).
Wenns schwierig wird, einen Compiler die Arbeit machen lassen, sich das
Ergebnis reinkopieren und sich dann stolz auf Brust klopfen: das ganze
Programm reine Assemblerprogrammierung.

Autor: juergen klauck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na ja
so einfach stelle ich mir das nicht vor -leider
man muss schon verstehen was da passiert sonst hat man keine chance
hab ich am anfang beim rechnen in asm gemerkt ;-{

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habs früher auch gemacht, zu 51er-Zeiten. Hatte nur den
Keil-Compiler in der Uni zur Verfügung. Beispielprogramme geschrieben,
compilieren lassen und aus den Listings dann meine Assembler-libarys
gebastelt...
Wir hattens hier schon öfter: schreib doch gleich das ganze Programm in
einer Hochsprache.

Autor: Thorsten (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hab das spasseshalber mal ausprobiert und folgendes Programm eingegeben
und für einen ATmega8 compiliert:

#include <math.h>

void main(void)
{
    float result, arg;

    arg = 2.;
    result = sqrt(arg);
}

Das Listing ist im Anhang, diese Zeilen verbrauchen 29% des Flash.
Hmmm....

Thorsten

Autor: juergen klauck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ui ui jui !!!
da werd ich wohl nen problem bekommen aber besten dank thorsten!
muss jetzt aber leiden feierabend machen ;-}}}}}
ich werd mal ne nacht drueber schlafen......
vieleicht trifft man sich ja morgen hier wieder ....
thx

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
google mal, irgenwo gibt es einen einfachen Algorithmus wie man eine
Wurzel zieht (hatte ich mir auch schonmal angeschaut, finde aber den
Links nichtmehr). Diese müsste kürzer sein und sich auch in Assembler
leicht implementieren lassen.

Autor: crazy horse (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ich fand das oben auch ein wenig dolle und habs mal mit CodeVision
compiliert, 280 words statt 1040. Laufzeit wäre mal interessant.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simuliert: 3370 Zyklen.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verwende doch das Newton-Verfahren. Erklärung, besonders auf Umsetzung
mit einer Rechenmaschine bezogen, findest Du hier:
http://groups.google.de/groups?hl=de&lr=&ie=UTF-8&...

Stefan

Autor: Peter Zimmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
es gibt das Heron verfahren. Dies geht als anäherung an die ganze
Sache. Leider weiß ich nicht mehr genau wie das geht. Aber es war
meines wissens mit den Grundrechenarten nicht sonderlich aufwendig.
Gruß
Peter

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.avrfreaks.net/Freaks/freakshow.php?proj...

; Very SMALL AVR code sqrt(num)
; adopted by Jack Tidwell
.def sqrt  = r0
.def numlo = r16
.def numhi = r17
.def subber = r24
.def subberh= r25

; Enter w/the 16bit number to take the sqrt of in r16,r17 (low/high)
Sqrt:
  clr  sqrt
  ldi  suber,1  ; initialize the seed to 1
  clr  suberh
loop:
  sub  numlo,subber
  sbc  numhi,subberh
  brlo  exit
  inc  sqrt
  adiw  subber,2  ; keep our "subber" ODD
  rjmp  loop
exit:
  ret             ; the sqrt(num) is in sqrt (r0), always an 8bit max


Nicht weiter von mir getestet.

Gruß hagen

Autor: buz11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Das Listing ist im Anhang, diese Zeilen verbrauchen 29% des Flash.
Hmmm...."


@Thorsten
Vielen Dank .

Ich mach seit 2 Jahren in assembler.
Und wollte eigentlich immer schon C können .
( alles nur für Privatgebrauch , nichts gewerbliches )

Bleibe wohl doch bei asm ...

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, es macht schon einen gewissen Unterschied, ob man die Wurzel aus
einer 16bit-Variablen zieht und als Ergebnis eine 8bit-Ganzzahl-Nummer
bekommt oder ob es eine float-Zahl ist. Wenn die Genauigkeit reicht,
warum nicht? Meist wird es aber nicht genügen. Und bei obigem Beispiel
sind es nicht mal 7% des flashs. Dazu kommt: es zwingt dich ja niemand,
die Routinen des Compilers zu benutzen, gilt genauso für die
vielgescholtene printf(), einfach zu benutzen, leider relativ viel
Code. Wenn er reinpasst, schön, habe ich nur gewonnen. Kann aber
genausogut die Ausgaben "zu Fuss" machen (mach ich auch manchmal wenn
es knapp wird).

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm wo ist der Unterschied, die Fließkommazahl vorher zu scalieren ?
Ist im Grunde sogar noch "einfacher" da die Mantisse meisten kleiner
als der entsprechende Integer Bereich ist, somit wird die Sqrt() aus
der Manitisse gezogen mit obiger Routine, ist auch nur eine Binärzahl,
und der Exponent wird halbiert.

Gruß Hagen

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zb. 0.81 * 10^2 = 81 = 9^2. Die Mantisse ist also 0.81, Sqrt(0.81) = 0.9
-> Exponent um 1 nach Rechts geschiften macht aus 10^2 -> 10^1, somit
0.9* 10^1 = 9.

Gruß Hagen

Autor: jeso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"
; Very SMALL AVR code sqrt(num)
; adopted by Jack Tidwell
.def sqrt  = r0
.def numlo = r16
.def numhi = r17
.def subber = r24
.def subberh= r25

; Enter w/the 16bit number to take the sqrt of in r16,r17 (low/high)
Sqrt:
  clr  sqrt
  ldi  suber,1  ; initialize the seed to 1
  clr  suberh
loop:
  sub  numlo,subber
  sbc  numhi,subberh
  brlo  exit
  inc  sqrt
  adiw  subber,2  ; keep our "subber" ODD
  rjmp  loop
exit:
  ret             ; the sqrt(num) is in sqrt (r0), always an 8bit max


"
kann mir jemand mal dieses Verfahren für das Wurzel ziehen schritt für 
schritt erklären.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es wird von der ursprünglichen Zahl jeweils eine
andere Zahl, die die Folge 1; 3; 5; 7; 9; ... (ungeraden Zahlen)
durchläuft abgezogen. Und zwar solange, wie das Ergebnis
der Subtraktion größer als 0 ist. Dabei wird mitgezählt,
wie oft subtrahiert werden kann und diese Anzahl ist dann das
Ergebnis

Hmm. Ob das tatsächlich eine Wurzel ausrechnet?

sqrt(78)

78 - 1   -> 77                1 mal
77 - 3   -> 74                2 mal
74 - 5   -> 69                3 mal
69 - 7   -> 62                4 mal
62 - 9   -> 53                5 mal
53 - 11  -> 42                6 mal
42 - 13  -> 29                7 mal
29 - 15  -> 14                8 mal
14 - 17  -> kleiner 0

Das Ergebnis ist also 8

Ineressant. Zumindest bei diesem Beispiel scheint es zu
funktionieren.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm.
Die Behauptung ist also

   n
  ----
  \                         2
  /     ( 2 * i ) + 1   =  n
  ----
  i = 0

und das stimmt tatsächlich.
Die Abstände zwischen den Qudratzahlen

   1     4     9     16    25    36    49
      3     5     7     9     11    13
         2     2     2     2      2

wachsen tatsächlich mit den ungeraden Zahlen.

Autor: Jankey (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
John Carmack in der ersten Doom Engine.:

__inline int Sqrt(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 fu**?
    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);
}

Autor: Kif (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sollte es nicht

   n-1
  ----
  \                         2
  /     ( 2 * i ) + 1   =  n
  ----
  i = 0

sein?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kif wrote:
> Sollte es nicht
>
>    n-1
>   ----
>   \                         2
>   /     ( 2 * i ) + 1   =  n
>   ----
>   i = 0
>
> sein?

Ja.
Bin beim Versuch eines vollständigen Induktionsbeweises auch
darüber gestolpert.


Trivialfall, n = 1

                 2
      2*0 + 1 = 1

            1 = 1

Annahme: n stimmt, Rückführung auf n-1

                          2
   Annahme: S(i,0,n-1) = n

                         2
    S(i,0,n-2) = ( n - 1)
                                      2
    S(i,0,n-1) - ( 2 (n-1) + 1 ) = (n - 1)

     2                     2
    n  - 2 (n - 1 ) - 1 = n - 2n + 1

    2
   n   kürzt sich weg

   -2n + 2 - 1 = -2n + 1

       -2n + 1 = -2n + 1


qed

Autor: jeso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sqrt(78)

78 - 1   -> 77                1 mal
77 - 3   -> 74                2 mal
74 - 5   -> 69                3 mal
69 - 7   -> 62                4 mal
62 - 9   -> 53                5 mal
53 - 11  -> 42                6 mal
42 - 13  -> 29                7 mal
29 - 15  -> 14                8 mal
14 - 17  -> kleiner 0

Das Ergebnis ist also 8

ist ja ein ganzen netter und relativ schneller allgotrithmus aber das 
ergebnis ist ja nicht 8 sonder in wirklichkeit 8,8 wie könnte man den 
code jetzt erweitern das man den rest auch noch berechnen kann

Autor: Stefanie B. (sbs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SQRT (78) =  8,8317608663278468547640427269593

also nach dem Komma  ,831
und 14/17 ergibt     ,823

also das ist schon nah dran, erfordert aber eine division...

Stefan

Autor: rene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Ganze mit 100 erweitern ? Anstelle 78 7800 nehmen.

Autor: Kif (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man könnte zB die Zahl um 100 skalieren, und anschließend das Ergebnis 
durch 10 teilen.
1  7799  >  1  mal
3  7796  >  2  mal
5  7791  >  3  mal
7  7784  >  4  mal
9  7775  >  5  mal
11  7764  >  6  mal
13  7751  >  7  mal
15  7736  >  8  mal
17  7719  >  9  mal
19  7700  >  10  mal
21  7679  >  11  mal
23  7656  >  12  mal
25  7631  >  13  mal
27  7604  >  14  mal
29  7575  >  15  mal
31  7544  >  16  mal
33  7511  >  17  mal
35  7476  >  18  mal
37  7439  >  19  mal
39  7400  >  20  mal
41  7359  >  21  mal
43  7316  >  22  mal
45  7271  >  23  mal
47  7224  >  24  mal
49  7175  >  25  mal
51  7124  >  26  mal
53  7071  >  27  mal
55  7016  >  28  mal
57  6959  >  29  mal
59  6900  >  30  mal
61  6839  >  31  mal
63  6776  >  32  mal
65  6711  >  33  mal
67  6644  >  34  mal
69  6575  >  35  mal
71  6504  >  36  mal
73  6431  >  37  mal
75  6356  >  38  mal
77  6279  >  39  mal
79  6200  >  40  mal
81  6119  >  41  mal
83  6036  >  42  mal
85  5951  >  43  mal
87  5864  >  44  mal
89  5775  >  45  mal
91  5684  >  46  mal
93  5591  >  47  mal
95  5496  >  48  mal
97  5399  >  49  mal
99  5300  >  50  mal
101  5199  >  51  mal
103  5096  >  52  mal
105  4991  >  53  mal
107  4884  >  54  mal
109  4775  >  55  mal
111  4664  >  56  mal
113  4551  >  57  mal
115  4436  >  58  mal
117  4319  >  59  mal
119  4200  >  60  mal
121  4079  >  61  mal
123  3956  >  62  mal
125  3831  >  63  mal
127  3704  >  64  mal
129  3575  >  65  mal
131  3444  >  66  mal
133  3311  >  67  mal
135  3176  >  68  mal
137  3039  >  69  mal
139  2900  >  70  mal
141  2759  >  71  mal
143  2616  >  72  mal
145  2471  >  73  mal
147  2324  >  74  mal
149  2175  >  75  mal
151  2024  >  76  mal
153  1871  >  77  mal
155  1716  >  78  mal
157  1559  >  79  mal
159  1400  >  80  mal
161  1239  >  81  mal
163  1076  >  82  mal
165  911  >  83  mal
167  744  >  84  mal
169  575  >  85  mal
171  404  >  86  mal
173  231  >  87  mal
175  56  >  88  mal
177  -121  >  Ergebnis negativ

Autor: Stefanie B. (sbs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
weiterhin fällt folgende Gesetzmäßigkeit auf:

die Zahl x, die abgezogen wird, um eins addiert,
gebrochen 2 ist das Ergebnis:

>
>sqrt(78)

>78 - 1   -> 77                1 mal
>77 - 3   -> 74                2 mal
>74 - 5   -> 69                3 mal
>69 - 7   -> 62                4 mal
>62 - 9   -> 53                5 mal
>53 - 11  -> 42                6 mal
>42 - 13  -> 29                7 mal
>29 - 15  -> 14                8 mal
>14 - 17  -> kleiner 0

 erste Zeile: (1+1)/2=1
 zweite Zeile: (3+1)/2=2
 ...
 (vor)letzteZeile: (15+1)/2=8

Gruss
Stefan

Autor: jeso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann mir jemand sagen wie ich bei nem 8051 eine 16Bit / 8bit division 
mache am besten mit dem hardware befehl div ab

Danke

die oben genannte rutiene hab ich schon implementiert

Autor: Martin Cibulski (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe einmal eine Wurzelfunktion in AVR-Assembler geschrieben.
Allerdings für 64bit-Double.


http://www.martin-cibulski.de/atm/mount_controller...

Die Funktion arbeitet mit einer Iteration. Vorlage war die Routine aus 
der 'Cephes'-Library von Steve Moshier.

http://www.moshier.net/doubldoc.html#sqrt

Gesucht sei: wurzel = SQRT(zahl)

Zuerst wird ein Näherungswert durch Halbieren des Exponenten gewonnen.
-> naeherung

ITERATION (
Dividieren: ergebnis = zahl / naeherung
Neue Näherung: naeherung = 0.5 * (ergebnis + naeherung)
)

Diese Interation konvergiert in 4 Durchgängen auf 16 Dezimalstellen.

Gruß,
Martin

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.