mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Division ATmega


Autor: Gaat11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Mich würde Interessieren, wie der ATmega Divisionen von ganzen Zahlen 
ausführt. Und warum rundet der µc das Ergebnis von 15/16 (0,94) auf 0 
und nicht auf 1?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Gaat11 schrieb:
> Und warum rundet der µc das Ergebnis von 15/16 (0,94) auf 0
> und nicht auf 1?

Das hat nichts mit dem ATmega zu tun, sondern mit der Programmiersprache 
C. Bei Division von zwei Integer-Zahlen und Speicherung in einer 
Integer-Variablen wird nur der Integer-Teil gespeichert. Und das ist die 
Zahl vor dem Komma.

Schlag einfach mal Dein C-Buch auf ... Kapitel Datentypen.

: Bearbeitet durch Moderator
Autor: Gaat11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Das hat nichts mit dem ATmega zu tun, sondern mit der Programmiersprache
> C. Bei Division von zwei Integer-Zahlen und Speicherung in einer
> Integer-Variablen wird nur der Integer-Teil gespeichert. Und das ist die
> Zahl vor dem Komma.
>
> Schlag einfach mal Dein C-Buch auf ... Kapitel Datentypen.

Genau so war das. Danke für die schnelle Antwort.

Autor: Georg B. (diereinegier)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gaat11 schrieb:
> Hallo.
>
> Mich würde Interessieren, wie der ATmega Divisionen von ganzen Zahlen
> ausführt. Und warum rundet der µc das Ergebnis von 15/16 (0,94) auf 0
> und nicht auf 1?

Ich nehme an, Du programmierst in C bzw. C++?
Da verhält sich die Integer-Division genau so: als Division ohne Rest, 
egal auf welcher CPU.

Autor: N. G. (newgeneration) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das macht der AVR nicht willkürlich, er hält sich damit an den 
C-Standard.
Dabei werden ganzzahlige Divisionen nicht gerundet, sondern die 
Nachkommastellen abgeschnitten

Gerundete Ergebnisse gehen so:
Ergebnis = (Dividend + Divisor/2) / Divisor

mfG
N.G.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil es bei ganzen Zahlen keine Rundung gibt.
Du kannst allerdings vor der Division den halben Divisor addieren.

Autor: Stefan K. (stefan64)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
https://www.mikrocontroller.net/articles/AVR-Tutorial:_Arithmetik8#Division

Wenn Du integer gerundet rechnen willst, dann addiere vor der Division 
den halben Divisor auf:

 n                         n + d/2
---     -> gerundet:     ----------
 d                            d

Die Division d/2 übersetzt der Compiler heutzutage nicht in eine 
aufwändige Division, sondern ersetzt sie durch einfaches Shift nach 
rechts.


Viele Grüße, Stefan

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan K. schrieb:
> Die Division d/2 übersetzt der Compiler heutzutage nicht in eine
> aufwändige Division, sondern ersetzt sie durch einfaches Shift nach
> rechts.

Nö, nur bei unsigned darf er das machen.
-1 / 2 = 0
-1 >> 1 = -1

Autor: Gaat11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan K. schrieb:
> https://www.mikrocontroller.net/articles/AVR-Tutor...
>
> Wenn Du integer gerundet rechnen willst, dann addiere vor der Division
> den halben Divisor auf:
>
>  n                         n + d/2
> ---     -> gerundet:     ----------
>  d                            d
>
> Die Division d/2 übersetzt der Compiler heutzutage nicht in eine
> aufwändige Division, sondern ersetzt sie durch einfaches Shift nach
> rechts.
>
> Viele Grüße, Stefan

Danke. Das werde ich mal versuchen.
Ps: Ich benutze unsgiend

Autor: Stefan K. (stefan64)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Peter D. schrieb:
> Nö, nur bei unsigned darf er das machen.

Ja, da gebe ich Dir recht. Aber auch in diesem Fall wird er keine 
Division daraus machen, sondern am Ende eine Shift-Operation:
  int n;   // Y + 3, Y +4
  int e;   // Y + 1, Y + 2

  e = n / 2;
     854:  2b 81         ldd  r18, Y+3  ; 0x03
     856:  3c 81         ldd  r19, Y+4  ; 0x04
     858:  33 23         and  r19, r19
     85a:  14 f4         brge  .+4        ; 0x860 <__stack+0x1>
     85c:  2f 5f         subi  r18, 0xFF  ; 255
     85e:  3f 4f         sbci  r19, 0xFF  ; 255
     860:  35 95         asr  r19
     862:  27 95         ror  r18
     864:  3a 83         std  Y+2, r19  ; 0x02
     866:  29 83         std  Y+1, r18  ; 0x01
Das ist ein gutes Beispiel, warum man solche mathematischen Funktionen 
(heutzutage) den Compiler machen lässt.

Gruß, Stefan

Autor: ASM Superprofi (Gast)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
>das macht der AVR nicht willkürlich, er hält sich damit an den
>C-Standard.

Selten so einen BLÖDSINN gelesen. Der AVR hält sich nur an seine eigenen 
Regeln!

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mich würde Interessieren, wie der ATmega Divisionen ... ausführt.

Bezogen auf den 8bit Befehlssatz:

Gar nicht. Er kann nur Integer Zahlen nur addieren, subtrahieren und 
schieben. Manche (aber nicht alle AVR') können außerdem Fließkommazahlen 
multiplizieren. Dividieren können sie nicht.

Bezogen auf die Programmiersprache:

Der Compiler zerlegt die Division in einfachere Teil-Operationen, die 
der Mikrocontroller kann. Im Prinzip so, wie man in der Schule auch das 
manuelle dividieren lernt.

Am Besten ist, du schreibst das einfach mal in C oder C++ auf und lässt 
Dir vom Compiler ein Listing (*.lst Datei) erstellen. Dann siehst du den 
Assembler-Code, der dabei heraus kommt.

Autor: ASM Superprofi (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Stefan K. schrieb:
> Peter D. schrieb:
>> Nö, nur bei unsigned darf er das machen.
>
> Ja, da gebe ich Dir recht. Aber auch in diesem Fall wird er keine
> Division daraus machen, sondern am Ende eine Shift-Operation:
>
>
>   int n;   // Y + 3, Y +4
>   int e;   // Y + 1, Y + 2
> 
>   e = n / 2;
>      854:  2b 81         ldd  r18, Y+3  ; 0x03
>      856:  3c 81         ldd  r19, Y+4  ; 0x04
>      858:  33 23         and  r19, r19
>      85a:  14 f4         brge  .+4        ; 0x860 <__stack+0x1>
>      85c:  2f 5f         subi  r18, 0xFF  ; 255
>      85e:  3f 4f         sbci  r19, 0xFF  ; 255
>      860:  35 95         asr  r19
>      862:  27 95         ror  r18
>      864:  3a 83         std  Y+2, r19  ; 0x02
>      866:  29 83         std  Y+1, r18  ; 0x01
> 
> Das ist ein gutes Beispiel, warum man solche mathematischen Funktionen
> (heutzutage) den Compiler machen lässt.
>
> Gruß, Stefan

Stimmt. Ein blöder ASM Programmierer würde wahrscheinlich sowas 
komisches wie

lsr r19
ror r18

daraus machen. Viel zu wenig Zyklen! Und womit soll denn dann bitteschön 
der ganze Flash gefüllt werden?

Autor: ASM Superprofi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was macht denn der Compiler wenn man unsigned int nimmt? Eventuell ist 
ja dieser "Code" dem signed geschuldet, obwohl es selten ein signed 
braucht.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
2 lesenswert
nicht lesenswert
ASM Superprofi schrieb:
> Stimmt. Ein blöder ASM Programmierer würde wahrscheinlich sowas
> komisches wie
>
> lsr r19
> ror r18
>
> daraus machen.

Genau.  Und dass -1/2 dann zu 32767 wird, daran stören sich nur 
haarspaltende Kleingeister.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ASM Superprofi schrieb:
> Was macht denn der Compiler wenn man unsigned int nimmt?
int div2 (int x)
{
    return x / 2;
}

unsigned udiv2 (unsigned x)
{
    return x / 2;
}

-->
div2:
  sbrc r25,7
  adiw r24,1
.L3:
  asr r25
  ror r24
  ret

udiv2:
  lsr r25
  ror r24
  ret

Autor: ASM Superprofi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, ich nehme meine Stichelei hiermit zurück ;)

Autor: holger (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
>Manche (aber nicht alle AVR') können außerdem Fließkommazahlen
>multiplizieren.

Also falls du den MUL Befehl meinst, der multipliziert keine
Fließkommazahlen;)

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.