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