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
oder einfacher (aber nicht immer ganz so exakt, da es einen Rundungsfehler in der Rundung gibt): (190+39/2)/39
@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
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.
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)
ein einfacher Vergleich des Rests mit der Hälfte des Divisors, die läßt sich durch Rechtsschieben ermitteln.
@Christoph Kessler Was bekommt man durchs Rechtsschieben von als 39?
@Christoph Kessler ich wollte sagen, das geht nur bei geraden Zahlen, wie schon Benedikt oben schrieb.
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?
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
Stevko, probier noch mal mit 16:11 als Uebung, bevor du die Routine fertig hast.
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
16/11 ist 1 Rest 5, 5 ist kleiner oder gleich INT(11/2)=5 also gerundetes Ergebnis = 1
@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?
"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
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?
> 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.
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.
@Christoph gerade deswegen schlage ich vor, anstatt von LSR, SUB zu benutzen. LSR wird irgendwo einen Fehler einfuehren oder man muss zig Bedingungen auswerten.
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
INC Divisor LSR Divisor CMP Rest,Divisor BRLT Fertig INC Ergebnis Fertig:
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
@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.
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.