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
Du könntest das doch in C programmieren und dann sehen, wie der Compiler das umsetzt.
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 ??
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.
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 ;-{
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.
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
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
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.
ich fand das oben auch ein wenig dolle und habs mal mit CodeVision compiliert, 280 words statt 1040. Laufzeit wäre mal interessant.
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
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
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
"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 ...
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).
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
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
" ; 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.
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.
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.
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); }
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
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
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
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.