Wie effizient gerade/ungerade unterscheiden

#2495332
Jalu schrieb:
> Steh gerade auf dem Schlauch:
>
> Wie unterscheide ich im uC (AVR Atmega) effizient ohne Division, ob eine
> Zahl gerade oder ungerade ist? Es geht nur um uint8_t von 20 bis 0.

uint8_t?

Nicht künsteln

   if( i % 2 == 0 )
     gerade
   else
     ungerade


Den Rest überlass dem Optimizer des Compilers
Gast #2495351
Mensch, klar - das ist schon fast peinlich. Danke an alle.

Karl-Heinz - uint8_t und künsteln - verstehe ich jetzt grad nicht. Soll 
doch nur heissen, geht um eine unsigned integer Zahl (obwohl's egal ist 
- vielleicht meinst Du ja das). Ich probiere den Modulo Ansatz mal aus - 
bin wirklich gespannt, ob der Compiler das genauso kurz macht, aber die 
anderen Ansätze sind fast eleganter.
#2495357
Jalu schrieb:
> Mensch, klar - das ist schon fast peinlich. Danke an alle.
>
> Karl-Heinz - uint8_t und künsteln - verstehe ich jetzt grad nicht.

künsteln bedeutet: Tricks mit "Wir wissen, dass das unterste Bit das 
alles aussagt"

> Soll
> doch nur heissen, geht um eine unsigned integer Zahl (obwohl's egal ist
> - vielleicht meinst Du ja das).

Genau. Unsigned war das Stichwort.
Der Compiler kennt diese Tricks alle. Und er weiß auch, wann er sie 
einsetzen darf und wann nicht. Du schreibst % und der Compiler macht 
daraus eine Bitabfrage.
#2495433
Hi,

also in Bascom würde ich schreiben:

Is_uneven = Variable.0    'Check even or uneven

oder eben

Is_even = Not Variable.0

Kann man in C nicht so direkt auf Bits zugreifen? Daß der Compiler das 
in allen Fällen ausmaskieren muß dürfte aber klar sein.

Gruß,
Norbert
Gast #2495510
Karl Heinz Buchegger schrieb:
> Der Compiler kennt diese Tricks alle. Und er weiß auch, wann er sie
> einsetzen darf und wann nicht. Du schreibst % und der Compiler macht
> daraus eine Bitabfrage.

Wann dürfte er es nicht?
Das sind äquivalente Aussagen und basieren auf keinen weiteren a-priori 
Informationen, die % nicht bereits fordert.

Genauso gut kann man fordern/schliessen, dass der Compiler - hätte er 
Hardware die effizienter die Division/den Rest berechnen würde - (a & 
((2^n)-1)) in a % (2^n) optimieren müsse.

Einfache/schnelle Lesbarkeit ist das Argument dagegen.
#2495530
Max schrieb:
> Karl Heinz Buchegger schrieb:
>> Der Compiler kennt diese Tricks alle. Und er weiß auch, wann er sie
>> einsetzen darf und wann nicht. Du schreibst % und der Compiler macht
>> daraus eine Bitabfrage.
>
> Wann dürfte er es nicht?

wenn i zb ein double wäre. Dann fällt man mit der direkten Bitabfrage 
kräftig aufs Maul, mit % erledigt das aber der Compiler nach wie vor 
richtig. Und im Zweifel hab ich lieber ein Programm welches richtig 
rechnet, selbst wenn es einen Tick langsamer ist. Das ist immer noch 
besser als ein Programm, welches zwar schneller ist, dafür aber falsche 
Ergebnisse liefert.

> Einfache/schnelle Lesbarkeit ist das Argument dagegen.

Einfache Lesbarkeit ist bei derartigen Low-Level 'Tricks' immer das 
Gegenargument. Als Programmierer soll man sich in erster Linie darum 
kümmern, dass man im Code die Operation so ausdrückt, wie man es als 
Mensch erwarten würde. Um die Low-Level Tricks kümmert sich der Compiler 
und der macht das zuverlässiger als der Programmierer.
#2495625
Max schrieb:
> Karl Heinz Buchegger schrieb:
>> Der Compiler kennt diese Tricks alle. Und er weiß auch, wann er sie
>> einsetzen darf und wann nicht. Du schreibst % und der Compiler macht
>> daraus eine Bitabfrage.
>
> Wann dürfte er es nicht?

Wenn es kein Binärrechner mehr ist. Eine Architektur die zb. trinäre 
Zahlensysteme als Rechenbasis benutzt, würde mit der UND Maskierung mit 
1 eine Teilbarkeit durch 3 testen statt wie bei binären Architekturen 
auf 2.

Zweites Argument ist das die als binär gespeicherte Zahl garnicht als 
Binärzahl interpretiert werden kann. Dabei nimmt man sich zB. ein Nibble 
des Bytes, programmiert alle Rechenoperationen immer so das in diesem 
Nibble bei zb. dem Wert 7 ein Überlauf entsteht und schwups steht in 
unserer binärem Speicher eine Zahlendarstellung die ähnlich wie die BCD 
Kodierung aber mit Zahlenbasis 7 arbeitet. Eine UND-Maskierung des LSBs 
mit 1 wäre hier dann sinnfrei um auf Teilbarkeit durch 2 zu testen. Ein 
binäres Word (16Bit) hätte also 4 solcher Nibbles die jedes für sich nur 
Werte im Bereich 0 bis 6 enthalten können. So hat man 4 Ziffern einer 
Zahl zur Basis 7 in einem 16 Bit binärem Speicher abgelegt. Und das geht 
mit jeder Basis im Set {2..16} die nicht selber durch 2 teilbar ist.

Hat der Compiler in beiden Fällen das Wissen um diese Darstellung dann 
wird er mit der Modulo Operation immer korrekte Antworten liefern.

Ergo: man sollte den Modulo Operator benutzen wenn der Source 
Plattformunabhängig sein soll.

Gruß Hagen
#2495632
Naja, wenn ein uC im Spiel ist geht es sogesehen um 
Lowlevel/Systemprogrammierung, da darf man sowas auch selbst machen. 
Kommentare werden bei so etwas gerne gesehen.

Immer eine gute Idee: die verschiedenen Möglichkeiten mal durch den 
Compiler jagen und anschliessend den Assembler-Output desselben bei 
einem Glas Wein lesen.
Gast #2495764
Hagen Re schrieb:
> Wenn es kein Binärrechner mehr ist. Eine Architektur die zb. trinäre
> Zahlensysteme als Rechenbasis benutzt, würde mit der UND Maskierung mit
> 1 eine Teilbarkeit durch 3 testen statt wie bei binären Architekturen
> auf 2.

Das ist nicht richtig.
Warum sollte für diese Maskierung ein logischer Operator genommen 
werden, statt entsprechender Analogie?
Vergiss nicht, dass & eine feste im 2-adigen Verankerten Semantik hat.
Wenn du 10 % 2 niederschreibst (also 10-ädig repräsentiert), kommt da 
bei dir 0 raus?

Hagen Re schrieb:
> Zweites Argument ist das die als binär gespeicherte Zahl garnicht als
> Binärzahl interpretiert werden kann.

Die Speicherungsart der Zahl ist irrelevant. Die Semantik ist wichtig. 
du kannst von mir aus die Bits kreuz und quer würfeln. Deine anderen 
Operationen müssen die Repräsentation auch berücksichtigen.

Karl Heinz Buchegger schrieb:
> wenn i zb ein double wäre. Dann fällt man mit der direkten Bitabfrage
> kräftig aufs Maul, mit % erledigt das aber der Compiler nach wie vor
> richtig.

Macht er nicht.
% auf double/float ist nur auf integral-Typen definiert. Float/double 
sind Keine. Entsprechende Implementierungen (fmod) etc sind nicht 
äquivalent nur ähnlich. Sie könnens gar nicht sein. Dinge wie 
fmod(18000000.0f,2.0f) können irgendwann kein entsprechnde Ergebnis 
liefern, wenn nur (innerhalb ihres Wertebereiches) der Divident im 
Vergleich zum Divisor groß genug ist.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.