Forum: Mikrocontroller und Digitale Elektronik Wie effizient gerade/ungerade unterscheiden


von Jalu (Gast)


Lesenswert?

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.

Danke

von Karl H. (kbuchegg)


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

1
if (Zahl & 1) printf("Zahl %u ist ungerade", Zahl);

von Ingo W. (Gast)


Lesenswert?

Das niederwertigste Bit ausmaskieren (x&1), wenn das Ergebnis ungleich 
0, dann ungerade.
mfG ingo

von Purzel H. (hacky)


Lesenswert?

Naja. Das niederwertigste Bit...

von Jalu (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Jalu (Gast)


Lesenswert?

OK - bin auch für lesbar. Danke.

von Norbert S. (norberts)


Lesenswert?

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

von DirkB (Gast)


Lesenswert?

Norbert S. schrieb:
> Kann man in C nicht so direkt auf Bits zugreifen?

Die Antwort stand schon da:
Ingo Wendler schrieb:
> Das niederwertigste Bit ausmaskieren (x&1), wenn das Ergebnis ungleich
> 0, dann ungerade.

Das & ist das binäre UND. Die 1 ist der Wert des LSBit

von Max (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Hagen R. (hagen)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

@KHB: % geht m.W. nicht für Gleitkommazahlen.

von Andreas D. (rackandboneman)


Lesenswert?

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.

von Max (Gast)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.