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
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
1 | if (Zahl & 1) printf("Zahl %u ist ungerade", Zahl); |
Das niederwertigste Bit ausmaskieren (x&1), wenn das Ergebnis ungleich 0, dann ungerade. mfG ingo
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.
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.
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
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
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.
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.
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.