Hallo pl,
1 + 0xFFFFFFFF - $value;
Ich würde sicherheitshalber 0xFFFFFFFF - $value + 1 rechnen, für den Fall, dass das System mit uint32 rechnet. Das Kommutativgesetz gilt nur in der reinen Mathematik, nicht unbedingt in der Computerarithmetik.
Und zur Theorie: eine negative Zahl wird im Zweierkomplement gespeichert, d.h. man flippt die Bits und addiert 1 dazu.
Bits flippen - ich mach's mal mit 16 Bit um kleinere Zahlen zu haben - ist das gleiche wie von 0xffff abziehen. "Bits flippen + 1" bedeutet demzufolge: Subtrahieren von 0x10000.
Macht man es nochmal, bekommt man 0x10000 - (0x10000 - x) = x
- zweifaches Negieren gibt also korrekt wieder den Ausgangswert.
D.h. wenn ich 123 und -60 addieren will, dann ist a als 0x007b gespeichert und b als 0xffc4. Addiere ich das mit den Bordmitteln eines 16-Bit Prozessors, kommt 0x003f und ein gesetztes Carry-Flag heraus. Was korrekt +63 ist. Weil - ich addiere ja 123 + (0x10000 - 60), und 0x10000 ist für einen 16-bit Prozessor das gleiche wie 0 und ein Carry-Bit. Weil ich aber weiß, dass ich da signed-int Werte und keine int-Werte addiert habe, beachte ich das Carry-Flag nicht, sondern nehme statt dessen das Overflow-Flag, das nach anderen Regeln bestimmt wird. TL;DR-Version: Addiere ich zwei Zahlen mit gleichem Vorzeichen und das Ergebnis hat das entgegengesetzte Vorzeichen, liegt ein Overflow vor. Sonst nicht.
Update: Ich sehe gerade, dass Janosch dazu einen schönen Beitrag im Wiki verfasst hat.
Rolf
sumpsi - posui - clusi