Forum: Mikrocontroller und Digitale Elektronik Wurzel ziehen asm


von juergen klauck (Gast)


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

von Thorsten (Gast)


Lesenswert?

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

von juergen klauck (Gast)


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 ??

von crazy horse (Gast)


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.

von juergen klauck (Gast)


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 ;-{

von crazy horse (Gast)


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.

von Thorsten (Gast)


Angehängte Dateien:

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

von juergen klauck (Gast)


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

von Benedikt (Gast)


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.

von crazy horse (Gast)


Angehängte Dateien:

Lesenswert?

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

von crazy horse (Gast)


Lesenswert?

Simuliert: 3370 Zyklen.

von Stefan (Gast)


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&selm=199604201558.a16291%40bn.maus.de

Stefan

von Peter Zimmer (Gast)


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

von Hagen (Gast)


Lesenswert?

http://www.avrfreaks.net/Freaks/freakshow.php?projectid=218&sid=c7bb4521aeb60002002e555444ca2b0e&offset=10&limit=1

; 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

von buz11 (Gast)


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 ...

von crazy horse (Gast)


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).

von Hagen (Gast)


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

von Hagen (Gast)


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

von jeso (Gast)


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.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von Jankey (Gast)


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);
}

von Kif (Gast)


Lesenswert?

Sollte es nicht

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

sein?

von Karl H. (kbuchegg)


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

von jeso (Gast)


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

von Stefanie B. (sbs)


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

von rene (Gast)


Lesenswert?

Das Ganze mit 100 erweitern ? Anstelle 78 7800 nehmen.

von Kif (Gast)


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

von Stefanie B. (sbs)


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

von jeso (Gast)


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

von Martin Cibulski (Gast)


Lesenswert?

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


http://www.martin-cibulski.de/atm/mount_controller_4/mc_4_asm_main/float_sqrt.asm

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

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
Noch kein Account? Hier anmelden.