Das Verhalten von PB bei "a % n" mit n Zweierpotenz und a Variable kann gefährlich sein, wenn man z.B. C oder Java nach PB übersetzen will, da dort ein anderes Verhalten ist.
Also z.B.: liefert Java:
C:
PB:
Machen also irgendwelche Algorithmen davon z.B: per Abs(x % 128) Gebrauch, um eine beliebige Zahl auf einen Wert zwischen 0 und 127 zu hashen, so würde die direkte Übersetzung zu schwer zu findenen Bugs im Programmverhalten führen, da bei Java und C z.B. Abs(-5 % 128) = 5, während bei PB Abs(-5 % 128) = 123 ist.
Nochwas zur Mathematik dahinter:
(Danke für den Link, remi)
Es gibt also die 'mathematische Version', die einen Wert auf seinen Rest zwischen 0 und n-1 abbildet, und eine 'symmetrische Version', die einen Wert auf seinen Rest zwischen -(n-1) und n-1 abbildet und dabei die Symmetrie (-a) % b = - (a % b) erhält.
(Und dann gibt es noch die PB-Version, die für Zweierpotenzen doch wieder unsymmetrisch ist).
Sieht man aber alle als Funktion auf einen Repräsentanten der Restklasse, ist nichts davon 'falsch' (nichteinmal das andersartige Verhalten von PB bei modulo Zweierpotenz) sondern alles korrekt:
So gibt es z.B. bei modulo 3 die 3 Klassen:
Klasse [0] besteht aus ..., -6, -3, 0, 3, 6, ...
Klasse [1] besteht aus ..., -5, -2, 1, 4, 7, ...
Klasse [2] besteht aus ..., -4, -1, 2, 5, 8, ...
Zur Identifizierung der Klasse kann deren Repräsentant frei gewählt werden, also gilt z.B. [0] = [-3] = [18]... also ist auch z.B. -5 % 3 = - 2 nicht verkehrt, sondern es wird nur auf einen anderen Repräsentanten abgebildet. Selbst sowas Abstruses wie -5 % 3 = -176 wäre also nicht falsch. Insbesondere ist wie oben in den Beispielen -7 % 4 = -3 (Java+C) dann genauso richtig wie -7 % 4 = 1 (PB)
Möchte man bei "modulo n" definitiv einen positiven Repräsentanten zwischen 0 und n-1 haben (wie es oft auch von vorneherein in mathematischen Definitionen von mod verlangt wird), kann man folgendes machen:
Code: Alles auswählen
Procedure PosMod(a, n) ; return a % n with a in [0, n-1]
Protected b.l
b = a % n
If b < 0
ProcedureReturn b + n ; 'shift representative' by n
Else
ProcedureReturn b
EndIf
EndProcedure
Debug PosMod(-5, 3)
Debug PosMod(-4, 3)
Debug PosMod(-3, 3)