Advanced
Java
Services
|
Modulo und Ganzzahldivision |
Im folgenden werden vier Fälle unterschieden, um das Vorzeichen des Modulorestes und der Ganzzahldivision
zu ermitteln. Die Ermittlung des Vorzeichens von a/b ist natürlich trivial, interessanter ist das
Vorzeichen von a%b. Es stellt sich heraus, daß die Javaregeln genau mit der mathematischen Theorie
übereinstimmen. Wem die Abhandlung zu abstrakt ist, der springt gleich ans Ende und liest die sehr
einfache Zusammenfassung der vier Fälle.
Fall 1 : a>=0 , b>0
Wir gehen zunächst aus von zwei Ganzzahlen a und b und fordern für diese beide Zahlen
a>=0 und b>0
Betrachtet man nun die Zerlegung
a = q*b + r und fordert q>=0 und 0<=r<b
so gibt es genau eine Zerlegung der Art
a = q*b + r wobei q und r eindeutig bestimmt sind.
In dieser Situation nennt man q den Wert der Ganzzahldivision und der Divisionsrest r
heißt modulo. Mit den Operatoren, die Java dafür zur Verfügung stellt, schreibt sich das
folgendermaßen:
q = a/b >=0 Ganzzahldivision
r = a%b >=0 Rest bei Ganzzahldivision (modulo)
Setzt man jetzt a=0, so ergibt sich sofort, daß q=0 und r=0 sein müssen. Für a>0 ergibt sich
q>=0 und r>=0 . Überlegen Sie sich als Übung, wann hier q=0 oder r=0 auftreten.
Zusammenfassung
a>0, b>0 => a/b>=0 , a%b>=0
a=0, b>0 => a/b=0 , a%b=0
Mit den folgenden Ausgaben können sie diese Regel bestätigen
System.out.println("26/7 = " + 26/7 );
System.out.println("26%7 = " + 26%7 );
System.out.println("0/7 = " + 0/7 );
System.out.println("0%7 = " + 0%7 );
Fall 2 : a<=0 , b<0
Wir schreiben die obige Zerlegung mit anderen Variablen und multiplizieren mit -1 :
a1 = q1*b1 + r1 mit a1>=0 , b1>0 , q1>=0 , r1>=0
-a1 = q1*(-b1) + (-r1)
Dafür schreiben wir nun
a = q*b + r mit a<=0 , b<0 , q>=0 und 0>=r>b
Auch diese Zerlegung ist wieder eindeutig und es ergibt sich für a=0 wieder q=0 und r=0, für
a<0 ergibt sich q>=0 , r<=0 .
Zusammenfassung
a<0 , b<0 => a/b>=0 , a%b<=0
a=0 , b<0 => a/b=0 , a%b=0
Mit den folgenden Ausgaben können sie diese Regel bestätigen
System.out.println("-26/-7 = " + (-26/-7) );
System.out.println("-26%-7 = " + (-26%-7) );
System.out.println("0/-7 = " + 0/-7 );
System.out.println("0%-7 = " + 0%-7 );
Fall 3 : a<=0 , b>0
Wir schreiben die erste Zerlegung mit anderen Variablen und multiplizieren mit -1 :
a1 = q1*b1 + r1 mit a1>=0 , b1>0 , q1>=0 , r1>=0
-a1 = (-q1)*b1 + (-r1)
Dafür schreiben wir nun
a = q*b + r mit a<=0 , b>0 , q<=0 und 0>=r>b
Auch diese Zerlegung ist wieder eindeutig und es ergibt sich für a=0 wieder q=0 und r=0, für
a<0 ergibt sich q<=0 , r<=0 .
Zusammenfassung
a<0 , b>0 => a/b<=0 , a%b<=0
a=0 , b<0 => a/b=0 , a%b=0
Mit den folgenden Ausgaben können sie diese Regel bestätigen
System.out.println("-26/7 = " + (-26/7) );
System.out.println("-26%7 = " + (-26%7) );
System.out.println("0/7 = " + 0/7 );
System.out.println("0%7 = " + 0%7 );
Fall 4 : a>=0 , b<0
Wir schreiben die erste Zerlegung mit anderen Variablen und multiplizieren mit -1 :
a1 = q1*b1 + r1 mit a1>=0 , b1>0 , q1>=0, r1>=0
a1 = (-q1)*(-b1) + r1
Dafür schreiben wir nun
a = q*b + r mit
a>=0 , b<0 , q<=0 und 0<=r<b
Auch diese Zerlegung ist wieder eindeutig und es ergibt sich für a=0 wieder q=0 und r=0, für
a>0 ergibt sich q<=0 , r>=0 .
Zusammenfassung
a>0 , b<0 => a/b<=0 , a%b>=0
a=0 , b<0 => a/b=0 , a%b=0
Mit den folgenden Ausgaben können sie diese Regel bestätigen
System.out.println("26/-7 = " + 26/-7 );
System.out.println("26%-7 = " + 26%-7 );
System.out.println("0/7 = " + 0/7 );
System.out.println("0%7 = " + 0%7 );
Datentypen für a%b
a%b ist für jeden primitiven Datentyp außer boolean sinngemäß berechenbar. So liefert etwa
4.7%1.5 das Ergebnis 0.2 .
Zusammenfassung
Die Zusammenfassung aller Fälle ergibt auch in der Situation a%b eine recht einfache Regel
a und b seien Ganzzahltypen (byte, short, char, int, long) | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Der Ergebnistyp ist der größere der beiden Typen von a und b, mindestens jedoch int | |||||||||||||
a%b | Das Vorzeichen von a%b ist das Vorzeichen von a (a>0 , b>0)
0%b
| ergibt 0 (b>0)
| a%0
| ArithmeticException wird zur Laufzeit geworfen
|
| a/b
| Das Vorzeichen wird nach den üblichen Vorzeichenregeln ermittelt.
| 0/b
| ergibt 0
| a/0
| ArithmeticException wird zur Laufzeit geworfen
| |
a und b seien Fließkommatypen (float, double) | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a%b | Das Vorzeichen von a%b ist das Vorzeichen von a.
0%b
| ergibt 0
| a%0
| ArithmeticException wird zur Laufzeit geworfen
|
| a/b
| Das Vorzeichen wird nach den üblichen Vorzeichenregeln ermittelt.
| 0/b
| ergibt 0
| a/0
| ArithmeticException wird zur Laufzeit geworfen
| Der Ergebnistyp ist der größere der beiden Typen von a und b, mindestens jedoch int
| |
Der Ergebnistyp ist der größere der beiden Typen von a und b, mindestens jedoch int | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a%b | Das Vorzeichen von a%b ist das Vorzeichen von a (a!=0 , b!=0)
0%b
| ergibt 0 (b>0)
| a%0
|
|
| a/b
| Das Vorzeichen wird nach den üblichen Vorzeichenregeln ermittelt.
| 0/b
| ergibt 0
| a/0
| ArithmeticException wird zur Laufzeit geworfen
| |