Laufzeit einer Division variiert

OP #5099145
Lesenswert?

Hallo,

ich programmiere einen STM32F0 mit CooCox und erhalte ein (für mich) 
merkwürdiges Verhalten.

Da meine Anwendung sehr zeitbegrenzt ist und ich auf jede µs achten muss 
bin ich gerade dabei meinen Code zu Optimieren.

Das merkwürdige Verhalten zeigt sich bei einer Rechnung:
1
 v=((Buffer[0]*K)/Buffer[1]);

Diese errechnet mir eine Spannung aus den Werten meines AD-Wandlers.

Die Datentypen sind uint16_t Buffer[2], uint32_t K=5029, int16_t v;

Was ist das merkwürdige Verhalten: Sobald meine Spannung über 1 Volt 
geht, so dauert die Berechnung 0,5µs länger und ich verstehe einfach 
nicht warum.
Das gleiche Verhalten zeigt sich, wenn ich den Nenner konstant halte und 
nur den Zähler ändere.
Konkret bedeutet das: Spannung<1V Buffer[0]= 1296
                                  Spannung>1V Buffer[0]=1810

Setze ich diese beiden zahlen ein und halte den Nenner konstant so 
erhalte ich auch dieses Verhalten. Ich kann es mir einfach nicht 
erklären. Ein Überlauf passiert ja nicht, da K als unsigned long int 
deklariert wurde.

Vielleicht hat jemand einen Tipp.
Meinen Assembler-Code poste ich noch:
1
137               v=((1810*K)/Buffer[1]); //Berechnete Spannung im Q3.12 Format
2
080005ac:   ldr r3, [pc, #204]      ; (0x800067c <DMA1_Channel1_IRQHandler+236>)
3
080005ae:   ldr r3, [r3, #0]
4
080005b0:   ldr r2, [pc, #204]      ; (0x8000680 <DMA1_Channel1_IRQHandler+240>)
5
080005b2:   muls r2, r3
6
080005b4:   ldr r3, [pc, #204]      ; (0x8000684 <DMA1_Channel1_IRQHandler+244>)
7
080005b6:   ldrh r3, [r3, #2]
8
080005b8:   movs r1, r3
9
080005ba:   movs r0, r2
10
080005bc:   bl 0x8001b88 <__udivsi3>
11
080005c0:   movs r3, r0
12
080005c2:   movs r2, r3
13
080005c4:   ldr r3, [pc, #192]      ; (0x8000688 <DMA1_Channel1_IRQHandler+248>)
14
080005c6:   str r2, [r3, #0]
OP #5099159
Lesenswert?

A. K. schrieb:
> Dass die Laufzeit von Divisionen generell von den zu dividierenden
> Werten abhängen kann ist nicht neu.

Okay, aber wie ist das verhalten zu erklären?
Weil der Compiler, bei bestimmten Werten die Division nicht mit einer 
Schiebeoperation ersetzen kann?

Rene K. schrieb:
> Versuche mal als festen Wert nicht die 1810 sondern die 1812 ;-)

Die 1810 habe ich nur zu Testzwecken eingesetzt, damit ich zwei Werte 
habe die unterschiedliches Verhalten zeigen

Oliver S. schrieb:
> Hast du dir denn mal __udivsi3 angeschaut, was das so macht?

Habe es noch nicht gefunden. Muss ich erstmal suchen nach der Funktion
Gast #5099161
Lesenswert?

Matthias H. schrieb:
> so dauert die Berechnung 0,5µs länger

Das ist aber nun keine Zeit, die ins Gewicht fallen sollte.
Wenn es Dir nicht gelingt, durch etwas geschicktere Programmierung die 
Laufzeit zu optimieren, takte den µC einen Tick schneller.
Vielleicht bringt ein anderer Compiler bessere Ergebnisse.
Wenn das Programm kurz ist, könnte eine Demoversion von IAR oder Keil 
ausreichen.
#5099165
Lesenswert?

Matthias H. schrieb:
> Rene K. schrieb:
>> Versuche mal als festen Wert nicht die 1810 sondern die 1812 ;-)
>
> Die 1810 habe ich nur zu Testzwecken eingesetzt, damit ich zwei Werte
> habe die unterschiedliches Verhalten zeigen

Ja, dann setze mal die 1812 ein - und schau nach deiner Zeit. Überleg 
einfach mal was die "0" in irgendeiner Berechnung macht - und was ein 
Compiler aus solch einer Berechnung anstellt.
#5099174
Lesenswert?

Matthias H. schrieb:
> Weil der Compiler, bei bestimmten Werten die Division nicht mit einer
> Schiebeoperation ersetzen kann?

Nur Divisionen durch konstante Zweierpotenzen sind durch eine 
Schiebeoperation ersetzbar. Ist hier aber keine Zweierpotenz, im 
Original nicht einmal eine Konstante, weshalb keine Schiebeoperation 
möglich ist.

Wenn man durch eine Konstante dividiert, kann man u.U. mit einer 
Multiplikation und etwas Zusatzkram auskommen. Das macht ein Compiler 
aber nicht zwangsläufig selber, zumal dabei eine Rundung unter die 
Räder kommen kann.

Übrigens ist auch die Laufzeit der ab Cortex M3 vorhandenen 
Hardware-Division von den Werten abhängig.
Moderator (Firma: Titel) Persönliche Seite #5099180
Lesenswert?

Wenn ich eine Funktion mit unterschiedlichen Werten aufrufe, dann 
erwarte ich idR. auch ein unterschiedliches Ergebnis. Dass zum Ermitteln 
des Ergebnisses unterschiedliche Abläufe greifen, erschient mir dabei 
als normales Verhalten.

Schreibe (und optimiere hinterher) einfach selber mal so eine 
Divisionsroutine, dass wirst du sehen, dass du abhängig vom Bitmuster 
andere Strategien und Wege gehen musst.

Matthias H. schrieb:
> Weil der Compiler, bei bestimmten Werten die Division nicht mit einer
> Schiebeoperation ersetzen kann?
Er kann nur in ganz, ganz seltenen Fällen die Division durch ein simples 
Schieben ersetzen. Lass die Division (die ist doch unsigned, oder?) mal 
so laufen 1810/510 und mal so 1810/512. Was kommt dabei raus?

Matthias H. schrieb:
> Bei <1296 ist es immernoch 0,5µs kürzer als bei >1810
Und was ist daran schlimm?
Du kannst dich niemals drauf verlassen, dass ein Funktionsaufruf in der 
Zeit 0 oder wenigstens immer gleich schnell abläuft.
Beitrag #5099187 wurde von einem Moderator gelöscht.
OP #5099190
Lesenswert?

1
          __udivsi3:
2
08001b88:   movs r2, #0
3
08001b8a:   lsrs r3, r0, #1
4
08001b8c:   cmp r3, r1
5
08001b8e:   bcc.n 0x8001c7a <__udivsi3+242>
6
08001b90:   lsrs r3, r0, #4
7
08001b92:   cmp r3, r1
8
08001b94:   bcc.n 0x8001c56 <__udivsi3+206>
9
08001b96:   lsrs r3, r0, #8
10
08001b98:   cmp r3, r1
11
08001b9a:   bcc.n 0x8001c26 <__udivsi3+158>
12
08001b9c:   lsrs r3, r0, #12
13
08001b9e:   cmp r3, r1
14
08001ba0:   bcc.n 0x8001bf4 <__udivsi3+108>
15
08001ba2:   lsrs r3, r0, #16
16
08001ba4:   cmp r3, r1
17
08001ba6:   bcc.n 0x8001bc4 <__udivsi3+60>
18
08001ba8:   movs r2, #255   ; 0xff
19
08001baa:   lsls r1, r1, #8
20
08001bac:   rev r2, r2
21
08001bae:   lsrs r3, r0, #16
22
08001bb0:   cmp r3, r1
23
08001bb2:   bcc.n 0x8001bba <__udivsi3+50>
24
08001bb4:   asrs r2, r2, #8
25
08001bb6:   lsls r1, r1, #8
26
08001bb8:   beq.n 0x8001c86 <__udivsi3+254>
27
08001bba:   lsrs r3, r0, #12
28
08001bbc:   cmp r3, r1
29
08001bbe:   bcc.n 0x8001bf4 <__udivsi3+108>
30
08001bc0:   b.n 0x8001bc4 <__udivsi3+60>
31
08001bc2:   lsrs r1, r1, #8
32
08001bc4:   lsrs r3, r0, #15
33
08001bc6:   cmp r3, r1
34
08001bc8:   bcc.n 0x8001bce <__udivsi3+70>
35
08001bca:   lsls r3, r1, #15
36
08001bcc:   subs r0, r0, r3
37
08001bce:   adcs r2, r2
38
08001bd0:   lsrs r3, r0, #14
39
08001bd2:   cmp r3, r1
40
08001bd4:   bcc.n 0x8001bda <__udivsi3+82>
41
08001bd6:   lsls r3, r1, #14
42
08001bd8:   subs r0, r0, r3
43
08001bda:   adcs r2, r2
44
08001bdc:   lsrs r3, r0, #13
45
08001bde:   cmp r3, r1
46
08001be0:   bcc.n 0x8001be6 <__udivsi3+94>
47
08001be2:   lsls r3, r1, #13
48
08001be4:   subs r0, r0, r3
49
08001be6:   adcs r2, r2
50
08001be8:   lsrs r3, r0, #12
51
08001bea:   cmp r3, r1
52
08001bec:   bcc.n 0x8001bf2 <__udivsi3+106>
53
08001bee:   lsls r3, r1, #12
54
08001bf0:   subs r0, r0, r3
55
08001bf2:   adcs r2, r2
56
08001bf4:   lsrs r3, r0, #11
57
08001bf6:   cmp r3, r1
58
08001bf8:   bcc.n 0x8001bfe <__udivsi3+118>
59
08001bfa:   lsls r3, r1, #11
60
08001bfc:   subs r0, r0, r3
61
08001bfe:   adcs r2, r2
62
08001c00:   lsrs r3, r0, #10
63
08001c02:   cmp r3, r1
64
08001c04:   bcc.n 0x8001c0a <__udivsi3+130>
65
08001c06:   lsls r3, r1, #10
66
08001c08:   subs r0, r0, r3
67
08001c0a:   adcs r2, r2
68
08001c0c:   lsrs r3, r0, #9
69
08001c0e:   cmp r3, r1
70
08001c10:   bcc.n 0x8001c16 <__udivsi3+142>
71
08001c12:   lsls r3, r1, #9
72
08001c14:   subs r0, r0, r3
73
08001c16:   adcs r2, r2
74
08001c18:   lsrs r3, r0, #8
75
08001c1a:   cmp r3, r1
76
08001c1c:   bcc.n 0x8001c22 <__udivsi3+154>
77
08001c1e:   lsls r3, r1, #8
78
08001c20:   subs r0, r0, r3
79
08001c22:   adcs r2, r2
80
08001c24:   bcs.n 0x8001bc2 <__udivsi3+58>
81
08001c26:   lsrs r3, r0, #7
82
08001c28:   cmp r3, r1
83
08001c2a:   bcc.n 0x8001c30 <__udivsi3+168>
84
08001c2c:   lsls r3, r1, #7
85
08001c2e:   subs r0, r0, r3
86
08001c30:   adcs r2, r2
87
08001c32:   lsrs r3, r0, #6
88
08001c34:   cmp r3, r1
89
08001c36:   bcc.n 0x8001c3c <__udivsi3+180>
90
08001c38:   lsls r3, r1, #6
91
08001c3a:   subs r0, r0, r3
92
08001c3c:   adcs r2, r2
93
08001c3e:   lsrs r3, r0, #5
94
08001c40:   cmp r3, r1
95
08001c42:   bcc.n 0x8001c48 <__udivsi3+192>
96
08001c44:   lsls r3, r1, #5
97
08001c46:   subs r0, r0, r3
98
08001c48:   adcs r2, r2
99
08001c4a:   lsrs r3, r0, #4
100
08001c4c:   cmp r3, r1
101
08001c4e:   bcc.n 0x8001c54 <__udivsi3+204>
102
08001c50:   lsls r3, r1, #4
103
08001c52:   subs r0, r0, r3
104
08001c54:   adcs r2, r2
105
08001c56:   lsrs r3, r0, #3
106
08001c58:   cmp r3, r1
107
08001c5a:   bcc.n 0x8001c60 <__udivsi3+216>
108
08001c5c:   lsls r3, r1, #3
109
08001c5e:   subs r0, r0, r3
110
08001c60:   adcs r2, r2
111
08001c62:   lsrs r3, r0, #2
112
08001c64:   cmp r3, r1
113
08001c66:   bcc.n 0x8001c6c <__udivsi3+228>
114
08001c68:   lsls r3, r1, #2
115
08001c6a:   subs r0, r0, r3
116
08001c6c:   adcs r2, r2
117
08001c6e:   lsrs r3, r0, #1
118
08001c70:   cmp r3, r1
119
08001c72:   bcc.n 0x8001c78 <__udivsi3+240>
120
08001c74:   lsls r3, r1, #1
121
08001c76:   subs r0, r0, r3
122
08001c78:   adcs r2, r2
123
08001c7a:   subs r1, r0, r1
124
08001c7c:   bcs.n 0x8001c80 <__udivsi3+248>
125
08001c7e:   mov r1, r0
126
08001c80:   adcs r2, r2
127
08001c82:   mov r0, r2
128
08001c84:   bx lr
129
08001c86:   b.n 0x8001c88 <__udivsi3+256>
130
08001c88:   push {r0, lr}
131
08001c8a:   movs r0, #0
132
08001c8c:   bl 0x8001c9c <__aeabi_ldiv0>
133
08001c90:   pop {r1, pc}
134
08001c92:   nop ; (mov r8, r8)
Gast #5099194
Lesenswert?

Alle mir bekannten Divisionsroutinen waren als Schleife ausgeführt.
Subsequent wurde da, abhängig davon ob ein Bit gesetzt ist, gearbeitet, 
oder ein Teil übersprungen.
Das hat natürlich zur Folge, dass je nach "Bitmuster" die Zeit, die zum 
Grübeln benötigt wird, variiert.

Ist alles logisch, wenn man sich mal daran erinnert, wie man ohne 
Taschenrechner dividiert. Ham' wir alle mal - anno Tobak - gelernt.
Gast #5099195
Lesenswert?

> Okay, aber wie ist das verhalten zu erklären?

Dividiere doch mal handschriftlich auf Papier. Du wirst sehen, daß der 
Zeitaufwand auch hier von den konkreten Werten abhängt.

Beim Computer ist der Grund prinzipiell der selbe.
OP #5099199
Lesenswert?

Amateur schrieb:
> Alle mir bekannten Divisionsroutinen waren als Schleife ausgeführt.
> Subsequent wurde da, abhängig davon ob ein Bit gesetzt ist, gearbeitet,
> oder ein Teil übersprungen.
> Das hat natürlich zur Folge, dass je nach "Bitmuster" die Zeit, die zum
> Grübeln benötigt wird, variiert.
>
> Ist alles logisch, wenn man sich mal daran erinnert, wie man ohne
> Taschenrechner dividiert. Ham' wir alle mal - anno Tobak - gelernt.

Stefan U. schrieb:
> Dividiere doch mal handschriftlich auf Papier. Du wirst sehen, daß der
> Zeitaufwand auch hier von den konkreten Werten abhängt.
>
> Beim Computer ist der Grund prinzipiell der selbe.

Ja das würde ich ja verstehen.
Was ich aber nicht verstehe, dass es unter einem bestimmten Wert weniger 
lang dauert wie über einem bestimmten wert. Eurer theorie nach mpsste es 
ja in beiden bereichen(drüber,drunter) unterschiedlich lange dauern...
#5099201
Lesenswert?

Welche Genauigkeit brauchst Du?

Ggf. kannst Du die Division durch eine Lookup-Tabelle ersetzen und damit 
um ein Vielfaches schneller werden. Natürlich brauchst Du dafür - je 
nach Genauigkeit - Einiges an Flash und es sollten nicht mehrere solche 
Berechnungen optimiert werden müssen.

Der Faktor k / Buffer[1] würde dabei in eine Tabelle ausgelagert.
Als Berechnung hast Du dann nur noch:

v = Buffer[0] * lookupTable[Buffer[1]];

Viele Grüße, Stefan
#5099207
Lesenswert?

Matthias H. schrieb:
> Ja das würde ich ja verstehen.
> Was ich aber nicht verstehe, dass es unter einem bestimmten Wert weniger
> lang dauert wie über einem bestimmten wert. Eurer theorie nach mpsste es
> ja in beiden bereichen(drüber,drunter) unterschiedlich lange dauern...

Dividiere mal von Hand 10.000 / 10 und 10.000 / 11 und messe nach, wie 
lange Du für jede dieser Divisionen brauchst.
Egal ob Du eine Division per Hand oder per Software ausführst: die Dauer 
wird massgeblich von den Werten abhängen.

Viele Grüße, Stefan
OP #5099215
Lesenswert?

Stefan K. schrieb:
> Der Faktor k / Buffer[1] würde dabei in eine Tabelle ausgelagert.
> Als Berechnung hast Du dann nur noch:
>
> v = Buffer[0] * lookupTable[Buffer[1]];

Stefan, das ist eine super Idee.

Allerdings hängt mein Faktor K von der Kalibrierung des AD-Wandlers zu 
Beginn ab und kann sich somit ändern. Eine Berechnung der LookupTable 
würde zu lange dauern, da Buffer[1] um 100 variiert...
Gast #5099241
Lesenswert?

Nimm als Beispiel die schriftliche Division wie sie in Europa in den 
Schulen gelehrt wird.

Dann tritt es auf, dass der Rest eines Zwischenschrittes, kleiner als 
der Divisor ist. Man nimmt also eine weitere Stelle hinzu um wieder eine 
Zahl zu erhalten, die grösser/gleich dem Divisor ist. Manchmal reicht 
das nicht und noch eine Ziffer muss dazu genommen werden. Dieses 
vergleichen von Rest und Divisor geht recht schnell und im Kopf, auch 
das hinzunehmen von weiteren Ziffern. Es geht aber langsamer als die 
eigentliche Division der soweit betrachteten Zahl.
Bei diesem Verfahren hängt die Geschwindigkeit nicht davon ab, wie groß 
der Divisor absolut ist oder wie groß er im Vergleich zum Dividend ist.

Klar, soweit?

Das ist nur mal eine prinzipielle Betrachtung. Wie das bei der 
Implementierung ist, hängt vom Verfahren ab. Auf dem Rechner gibt es 
mehrere Möglichkeiten eine Division effizient zu implementieren.


Nun noch eine Bemerkung zu diesen beiden Sätzen, wenn Du gestattest:

> ...dass es unter einem bestimmten Wert weniger
lang dauert wie über einem bestimmten wert.

> Eurer theorie nach müsste es ja in beiden Bereichen (drüber,drunter)
> unterschiedlich lange dauern ...

sagen das selbe aus, widersprechen sich gegenseitig nicht.
#5099248
Lesenswert?

Matthias H. schrieb:
> Allerdings hängt mein Faktor K von der Kalibrierung des AD-Wandlers zu
> Beginn ab und kann sich somit ändern. Eine Berechnung der LookupTable
> würde zu lange dauern, da Buffer[1] um 100 variiert...

Du musst die Lookup-Table doch nur einmal nach der Kalibrierung rechnen. 
Und wenn Buffer[1] sich nur um den Faktor 100 ändert, dann bleibt die 
Lookup-Table im RAM auch überschaubar klein.

Viele Grüße, Stefan
Gast #5099257
Lesenswert?

Dezimal Binär
529     1000010001     (3 Einser)
415     0110011111     (7 Einser)
Die Laufzeit der Division hat nur beschränkt etwas mit der Größe der 
Zahlen zu tun.
Bei der schrittweisen Abarbeitung von 529 wird nur Dreimal gearbeitet 
und Neunmal ein Teil übersprungen.
Bei 415 sieht das Ganze etwas anders aus. Obwohl, als Zahl gesehen 
dieser Wert kleiner ist als der Vorherige, wird hier Siebenmal 
gearbeitet und nur Dreimal etwas übersprungen.

Das Ganze ist zwar etwas vereinfacht, aber wenn du im oberen Falle mal 
die Laufzeiten ins Auge fasst, wirst Du sehen, dass die "größere" Zahl 
schneller bearbeitet wird wie die kleinere.
Oder Umgekehrt: Die Annahme, das größere Zahlen länger brauchen, wie 
kleinere, ist nicht richtig.

Der Mensch ist halt auf das dezimale System getrimmt.
Für ihn ist 500 eine gerade Zahl. Computy sieht das aber ganz anders. 
Für ihn ist 512 sehr gerade. 0111110100 (500d) : 1000000000 (512d).
#5099263
Lesenswert?

Amateur schrieb:
> Bei der schrittweisen Abarbeitung von 529 wird nur Dreimal gearbeitet
> und Neunmal ein Teil übersprungen.

In
  08001c5a:   bcc.n 0x8001c60 <__udivsi3+216>
  08001c5c:   lsls r3, r1, #3
  08001c5e:   subs r0, r0, r3
wird entweder gesprungen oder es werden 2 Eintakter ausgeführt. Je nach 
Tempo des nichtsequentiellen Zugriffs kann das deutlich oder 
laufzeitneutral ausfallen. Der Unterschied kann daher auch davon 
abhängen, ob Code in RAM oder Flash.

Matthias H. schrieb:
> so dauert die Berechnung 0,5µs länger

Wieviel Takte sind das?
Beitrag #5099271 wurde von einem Moderator gelöscht.
Gast #5099275
Lesenswert?

Solche Division sind in der Regel nur nötig wenn du den Wert anzeigen 
willst.
Rechne einfach mit der Auflösung des ADC weiter.

Es ist ja schon eine Spannung in Volt. Halt mit einer unschönen 
Auflösung.

Deine anderen Spannungswerte z.B Grenzen  für Signal Range Check musst 
du halt auch in dieser Auflösung angeben.

Veränderung der Auflösung innerhalb des Programms ist nur ein Komfort 
für den Programmierer. Wenn Laufzeit kritisch ist sollte man sie nicht 
dafür verschwenden.

Umgerechnet wird beim Senden oder Ausgeben.
#5099283
Lesenswert?

Matthias H. schrieb:
> Stefan U. schrieb:
>> Dividiere doch mal handschriftlich auf Papier. Du wirst sehen, daß der
>> Zeitaufwand auch hier von den konkreten Werten abhängt.
>> Beim Computer ist der Grund prinzipiell der selbe.
>
> Ja das würde ich ja verstehen.
> Was ich aber nicht verstehe, dass es unter einem bestimmten Wert weniger
> lang dauert wie über einem bestimmten wert. Eurer theorie nach mpsste es
> ja in beiden bereichen(drüber,drunter) unterschiedlich lange dauern...

Das ist auch so. Tatsächlich hängt die Laufzeit der Division nicht nur 
vom Divisor ab (weil du dich so an verschiedene Werte des Divisors 
klammerst) sondern sowohl vom Divisor als auch vom Dividenden.

Das ist ganz normal und sollte jedem Programmierer auch bekannt sein. 
Wenn dein Programm nur dann funktioniert, wenn die Laufzeit der Division 
immer gleich ist, dann funktioniert es nicht. Schreib es anders.
OP #5099287
Lesenswert?

Volle22 schrieb:
> Solche Division sind in der Regel nur nötig wenn du den Wert anzeigen
> willst.
> Rechne einfach mit der Auflösung des ADC weiter.
>
> Es ist ja schon eine Spannung in Volt. Halt mit einer unschönen
> Auflösung.
>
> Deine anderen Spannungswerte z.B Grenzen  für Signal Range Check musst
> du halt auch in dieser Auflösung angeben.
>
> Veränderung der Auflösung innerhalb des Programms ist nur ein Komfort
> für den Programmierer. Wenn Laufzeit kritisch ist sollte man sie nicht
> dafür verschwenden.
>
> Umgerechnet wird beim Senden oder Ausgeben.

Ja aber ich habe eine Offsetkorrektur. Z.B will ich von dem Wert 2,5V 
abziehen. Woher weiß ich jetzt welcher digitale Zahlenwert 2,5V 
entspricht?

Mein VDDA, sprich die Referenz, varriert nämlich
#5099294
Lesenswert?

Axel S. schrieb:
> Das ist ganz normal und sollte jedem Programmierer auch bekannt sein.
> Wenn dein Programm nur dann funktioniert, wenn die Laufzeit der Division
> immer gleich ist, dann funktioniert es nicht. Schreib es anders.

Wenn man in obigem __udivsi Code die Anfangstests weglässt, das also auf 
die klassische Divisions-Iteration reduziert, und ihn auf einem Cortex 
M0 ohne Waitstates ausführt (z.B. im RAM), ist der Code laut ARM-Doku 
laufzeitneutral. Der ausgeführte Sprung der entrollten Iteration dauert 
genauso lang wie der nicht ausgeführte Sprung plus die beiden Eintakter.

Eine sichere Bank für alle Lebenslagen ist das natürlich nicht.
Gast #5099296
Lesenswert?

>Ich werden jetzt erstmal mit einer Lookup Table arbeiten, was
>mir wirklich Zeit einspart.

Vorsicht bissiger Hund!

Sind der FLASH-Speicher oder das RAM beschränkt, so bekommst Du bei der 
Verwendung von Tabellen sehr schnell dicke Backen (sehr Platzintensiv). 
Vor allem, wenn Du den Wertebereich nicht ordentlich einschränken 
kannst.
#5099497
Lesenswert?

> Ja das würde ich ja verstehen.
> Was ich aber nicht verstehe, dass es unter einem bestimmten Wert weniger
> lang dauert wie über einem bestimmten wert. Eurer theorie nach mpsste es
> ja in beiden bereichen(drüber,drunter) unterschiedlich lange dauern...

Programmiere doch mal selber eine Division in Assembler. Hinweis: 
Schriftliche Division wie in der 3. Klasse. Dann wird klar, warum die 
Regenzeit der Division unterschiedlich lang wird.

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