Unterschied zweier Variablen

#367620
Lesenswert?

"Hmmm...dürfte wohl bei sehr grosszügigem Einsatz einiges an
Rechenleistung kosten..."


Nö, überhaupt nicht.

Is ja nur ein Test und ne Subtraktion.
Aufm ATMega88 bei 20MHz unter WINAVR dauerts max 0,3µs:
1
c = a > b ? a - b : b - a;
2
  5c:   68 17           cp      r22, r24
3
  5e:   18 f4           brcc    .+6             ; 0x66 <test+0xa>
4
  60:   86 1b           sub     r24, r22
5
  62:   68 2f           mov     r22, r24
6
  64:   01 c0           rjmp    .+2             ; 0x68 <test+0xc>
7
  66:   68 1b           sub     r22, r24

Ist bestimmt 100 mal schneller als in Java.


Peter
Gast #367621
Lesenswert?

Wieder einer der glaubt, dass etwas, das sich kurz schreibt auch nicht
lange dauern kann und sich dann wundert, dass ein klitzekleines printf
oder so (am besten noch in einer ISR) das ganze System abschießt...

Aber im Ernst: Ich kenne mich mit Java nicht sonderlich aus, denke
aber, dass hinter der Schreibweise 'Math.abs(a - b)' im Prinzip nix
anderes (zumindest nicht viel anderes) steckt als das, was Peter
gepostet hat. Und kürzer gehts nun wirklich nicht!
Gast #367624
Lesenswert?

Ich habe damit keine Schwierigkeiten, aber abs() drückt eben einfach
besser die Absicht aus, ähcnlich wie

    loop_until_bit_is_clear(PORTB, PORTB5);

die Absicht besser ausdrückt, als:

    while (PORTB & (1 << PORTB5);

obhwohl ich auch mit letzterem kein Problem habe, es zu lesen.
Gast #367626
Lesenswert?

Natürlich hab ich das gleich nach dem Abschicken gemerkt, aber ich
dachte mir, ich brauch's nicht extra erwähenen, weil das bestimmt
schon ein anderer innerhalb von weniger als 5 Mintuen tun wird. ;-)
#367628
Lesenswert?

@Karl Heinz

"#define ABS( a )  (a) < 0 ? (a) : -(a)"


Und schon bist Du in die Falle getappt !

a und b sind vom Typ uint8_t, also unsigned und damit ist der Ausdruck
(a) < 0 immer falsch.

Das AVR-GCC abs-Macro erweitert deshalb auf signed int, macht dann erst
die Subtraktion, dann den Betrag und schmeißt das High-Byte wieder weg.
Deshalb dauert es auch länger.
Ob das der AVR-GCC nur zufällig so macht wie gewünscht, weiß ich
nicht.
abs() auf unsigned klingt jedenfalls irgendwie sinnlos.

Daher finde ich a > b ? für unsigned Werte besser lesbar als abs(). Und
ich habe die Garantie, daß er genau das macht, was ich will.


Peter
Gast #367630
Lesenswert?

Hallo

Könnte das mit dem unsigned mein Problem sein?

uint8_t d = (ADCH > gbc_ee_buffer) ? (ADCH - gbc_ee_buffer) : 29;

Dieser Ausdruck ist immer falsch, d.h. ich kriege immer 29... (Obwohl
es mehr als nur schlüssige Hinweise gibt, dass sowohl ADCH wie auch
gbc_ee_buffer mal grösser sind.)

Was ich meinte wegen langsam: Ich habe auf ne Lösung gehofft à la
'subtrahieren' und dann irgend wo vielleicht noch ein Bit drehen oder
so... Hoffentlich hält ihr mich jetzt nicht für total naiv ;-) - ich
sollte mich aber echt mal mit der grundlegenden Art und Weise, wie
Zahlen gespeichert und verarbeitet werden, befassen! ^^

Gruss

Michael
Gast #367631
Lesenswert?

Schreib statt der 29 mal ne 42 rein, vielleicht klappts dann besser;-)

Im Ernst: Man kann es sso versuchen, wie man es in Assembler machen
kann: Einfach ins blaue hinein subtrahieren. Wenn was negatives
rauskommt, gibts nen Underrun in der Zielvariable. Dann das
Zweierkomplement aufdröseln (MSB checken, wenn gesetzt, dann
Bitkomplement bilden und eins dazuaddieren) und --Zack-- hat man den
Betrag.
Gast #367634
Lesenswert?

> Ich habe auf ne Lösung gehofft à la 'subtrahieren' und dann irgend
> wo vielleicht noch ein Bit drehen oder so...

Sowas in der Art geht schon, aber wird dann schwierig in C. Wenn's dir
auf Geschwindigkeit und Codegröße ankommt, wird's wohl am besten
Assembler sein. Etwa sowas wie das müßte gehen:

    sub r16, r17
    brsh next
    neg r16
next:
Gast #367637
Lesenswert?

Peters Code geht immer dann schief, wenn die Differenz der beiden
8bit-Zahlen größer als 127 ist.
Aber setzt der Compiler diesen C-Code wirklich in Rolfs Assemblercode
um?
Rolf testet das Carry-Flag, Peter das Vorzeichenbit?
Gruß
Gast #367639
Lesenswert?

Um noch den Unterschied zu erläutern: Peter geht davon aus, daß nach der
Subtraktion a (wenn man es als vorzeichenbehaftet interpretiert) negativ
ist, wenn es vorher kleiner als b war. Diese Annahme ist aber nur dann
in jedem Fall korrekt, wenn a und b auch tatsächlich
vorzeichenbehaftete Zahlen sind. Für vorzeichenlose Zahlen muß der
Vergleich anders aussehen. Deshalb enthält mein Asssembler-Code auch
ein brsh (vorzeichenloser Vergleich) und kein brge
(vorzeichenbehafteter Vergleich).
#367640
Lesenswert?

@Rolf,

hast recht.

Mich hat nur das BRSH verwirrt, da muß ich immer nachsehen, welches
Flag damit gemeint ist.
Ich schreib lieber BRCC, dann weiß ich, daß es das Carry ist.

Das Carry ist praktisch das 8. Ergebnisbit, aber leider unter C nicht
verfügbar.


Peter
Gast #367641
Lesenswert?

Ich habe mir hier über die Flags ehrlich gesagt überhaupt keine Gedanken
gemacht, sondern einfach den Befehl genommen, der beim Vergleich zweier
vorzeichenloser Zahlen springt, wenn die erste größer oder gleich der
zweiten ist.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren