mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Runden einer Division in ASM


Autor: Stevko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe (AVR-)ASM Freunde,

ich habe mich soeben an einem Problem festgefressen und sehe den Wald
vor lauter Bäumen nicht mehr.

Mein Problem ist eine simple Division von 8(Bit) / 8(Bit) aber
gerundet.

Mal ein Beispiel:
190:39=4,871... --> gerundet = 5 !

So, die Divisionsroutine bringt mir die 4 als Hauptergebnis und als
ganzzahliger Rest = 34. Ich finde aber, wahrscheinlich vor lauter
Rechnen, keinen Ansatz damit das Hauptergebnis 4 auf 5(wegen Rundung)
verändert wird. Im Hinterkopf habe ich noch die Formel A=A+B/2! Mit der
probiere ich jetzt schon 1 Stunde rum, jedoch ohne gescheites Ergebnis.


Also ich bin schon richtig konfus und zweifle an meinen Fähigkeiten.
Mir fehlt irgendwie der entscheidende Schritt.

Gruß
  Stevko

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(2*190+39)/(2*39)

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder einfacher (aber nicht immer ganz so exakt, da es einen
Rundungsfehler in der Rundung gibt):

(190+39/2)/39

Autor: Stevko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@romanua:

Die Lösung ist zwar richtig, aber bedenke das ich mich im 8-Bit-Bereich
aufhalte.

--> 2*190 = ? = > 8Bit

Ich progamiere in ASM und meines Wissens gab es dafür eine einfache
Lösung. Irgendwas mit Schieben und Rotieren, ich habe es schon mehrmals
hier gelesen und es war so simpel, das ich es nicht notiert habe. Nach
dem Motto: "Alles klar. Das ist ja so einfach!" Doch jetzt wo ich vor
dem Problem stehe, ist es klar wie Kloßbrühe.

Gruß
  Stevko

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das stimmt, kannst du nur 6-bit machen. Wenn du einen Fehler in der
Rundung haben darfst, kannst Du die Methode von Benedikt mit 7-bit
einsetzen.

Nimm doch 16-bit Division. Schieben und Rotieren hoert sich nach
Multiword Arithmetic an, wenn so, dann doch mehr als 8-bit.

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast aber auch den Restbetrag, habs uebersehen.

Integer(A/B), Rst(A/B)

if B-Rst(A/B)<Rst(A/B)
   Result:=Integer(A/B)+1
   elseif
   Result:=Integer(A/B)

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry =<

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
34/39  ist größer als 0,5, also muß aufgerundet werden.

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ein einfacher Vergleich des Rests mit der Hälfte des Divisors, die läßt
sich durch Rechtsschieben ermitteln.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Christoph Kessler

Was bekommt man durchs Rechtsschieben von als 39?

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Christoph Kessler

ich wollte sagen, das geht nur bei geraden Zahlen, wie schon Benedikt
oben schrieb.

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das unterste Bit fällt rechts raus, aus 39/2 wird 19 statt 19,5  Die
Rundungsgrenze liegt zwischen 19/39 (Abrunden) und 20/39 (Aufrunden).
Stimmt doch oder nicht?

Autor: Stevko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen

und Danke für die Antworten.

@Peter:
Ja das ist es was ich gesucht habe. Also probieren wir es mal aus.

 190:39=4,871...

-> a0 = 4  (Intergebnis)
   b0 = 34 (ganzzahliger Rest)
   t0 = Hilfsvariable


  mov  t0, b0    ;T = B = 34
  lsr  t0    ;T / 2 = 17
  add  a0, t0    ;A = A + B / 2 -> 21 = 4 + 17

Ne so gehts nicht.
Oder muß man das vorher addieren?

-> a0 = 190
   b0 = 39
   t0 = Hilfsvariable

  mov  t0, b0    ;T = B = 39
  lsr  t0    ;T / 2 = 19
  add  a0, t0    ;A = A + B / 2 -> 209 = 190 + 19

     Division
      geschiebe + rotiere

   Ergebnis = 5,3 -> Int_5

Aha so gehts, da konnte ich mich ja tot-probieren. Ich habe immer nach
einer Lösung hinter der Division gesucht.
Der Nachteil dieser Lösung ist aber ein Überlauf, z.B. 250:20.

Gruß
  Stevko

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stevko, probier noch mal mit 16:11 als Uebung, bevor du die Routine
fertig hast.

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich kapier immer noch nicht warum man das so kompliziert machen muß.
Wenn Divisor und Rest vorliegen, sind das doch nur drei Operationen.
Die 190 nochmal reinzunehmen ist völlig unnötig. Die "39" einmal
rechts schieben und mit der "34" vergleichen. wenn 34 wie hier größer
19 dann zum Ergebnis "4" eins addieren, sonst bleibts bei der 4

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
16/11 ist 1 Rest 5,
5 ist kleiner oder gleich INT(11/2)=5
also gerundetes Ergebnis = 1

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Christoph

habe nicht verstanden, wo du gleich mitreinnimmst zu "kleiner" oder
zu "groesser"

Dann dieses Beispiel:

6/4 ist 1 Rest 2

2 ist kleiner oder gleich INT(4/2)=2

also gerundetes Ergebnis = 1

stimmts?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"ich kapier immer noch nicht warum man das so kompliziert machen
muß."

Was ist denn daran so kompliziert ?

q = (a + b/2) / b;


Aber bei Dir sinds sogar noch 2 Schritte mehr:

q, rest = a / b, a % b;

if( rest * 2 > b )
  q++;


Peter

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter,

Christophs 2 extra Schritte sollten einen Ueberlauf verhindern, wenn
man 8-bit eine ASM (int+rest) Routine hat, sind aber rechnerisch
falsch.

Meine 2 extra Schritte verhindern den Ueberlauf und sind rechnerisch
korrekt, meine ich

if B-Rst(A/B)=<Rst(A/B)
   Result:=Int(A/B)+1
elseif
   Result:=Int(A/B)

Hat jemand ein Beispiel, wo es ein falsch abgerundetes Ergebnis
liefert?

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was ist denn daran so kompliziert ?
>
> q = (a + b/2) / b;

Na ja, das kann kompliziert werden, wenn a + b/2
einen Überlauf produziert.
Was man noch untersuchen müsste ist, wie jetzt ein
mögliches negatives Vorzeichen von a oder b (oder beiden)
da mit eingeht und sich auswirkt.

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit 6/4 stimmt, ich muß doch vor dem Halbieren 1 addieren,
entsprechend einer Addition von 0,5 beim dezimalen Runden, das geht mit
INC Divisor am einfachsten, solange er unter 255 bleibt.
Für die 6/4 muß dann "kleiner als" bzw. "größer oder gleich" die
Grenze bilden, sonst stimmts immer noch nicht.

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Christoph

gerade deswegen schlage ich vor, anstatt von LSR, SUB zu benutzen.


LSR wird irgendwo einen Fehler einfuehren oder man muss zig Bedingungen
auswerten.

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und sogar mit Divisor 255 klappts, der INC setzt das Carryflag, beim
Halbieren durch rechtsschieben kommt das ins MSB runter, egibt
$80=128.
es ist auf keinen Fall mehr 16Bit-Arithmetik nötig, wenn die
eigentliche Division erledigt ist.
Von negativen Zahlen war in der Aufgabe nicht die Rede, mit
Zweierkomplementdarstellung wird alles etwas komplizierter

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
INC Divisor
LSR Divisor
CMP Rest,Divisor
BRLT Fertig
INC Ergebnis
Fertig:

Autor: Stevko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, habe jetzt wieder mal ein wenig Zeit. Mein Dank geht an Alle die
hier mitwirken. Wie Ihr seht ist es nicht so einfach gewesen aber mehr
Köpfe = mehr Ideen!

Der Vorschlag von Christph sieht doch ganz passabel aus. Werde Ihn
heute Abend mal testen. Jedenfall ist das Problem mit dem Überlauf
vorläufig vom Tisch.

Gruß
  Stevko

Autor: romanua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Divisor=r1
@Difference=r1
@Rest=r2
@Ergebnis=r3

SUB Divisor, Rest     ;Difference=Divisor-Rest
CMP Rest,Difference   ;Set Flags
BRLT Fertig           ;exit if Difference > Rest
INC Ergebnis
Fertig:

Ich werd verrueckt noch einmal. Das gehts doch schneller und richtiger
als mit rechtsschieben.

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.