• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Rest- und Ganzzahl-Funktionen

regexer

Advanced Hacker
Hallo zusammen!

Zur Zeit muss ich mich in eine neue Scriptsprache einarbeiten. In diesem Zuge soll ich unter anderem eine bestehende Applikation (geschrieben in einer anderen Programmiersprache) in der neuen Umgebung "nachprogrammieren".
In diesem Zusammenhang machte ich eine interessante Entdeckung bezüglich Rest- und Ganzzahl-Funktionen. Ich muss aber zur Erklärung des Phänomens etwas weiter ausholen:

Wir stellen zuerst einmal fest: "8 geteilt durch 3 ist 2 Rest 2". Das ist wohl jedem klar. Ich werde im folgenden die verkürzte Schreibweise "8 mod 3 = 2" verwenden.
Meine erste Frage: Was ist mit Nachkommastellen?
Logisch wäre erstmal aus meiner Sicht:
8,8 mod 3 = 2,8
Oder wenn der Divisor Nachkommastellen hätte:
8 mod 3,1 = 1,8
Beziehungsweise wenn beide Zahlen Nachkommastellen haben:
8,8 mod 3,1 = 2,6

So weit so gut! Doch was ist, wenn auch noch Vorzeichen (also Plus und Minus) mit ins Spiel kommen?
Auch hier gibt es mehrere Möglichkeiten.
Die Einfachste ist aus meiner Sicht:
-8,8 mod 3,1 = -2,6
Relativ logisch ist auch noch:
-8,8 mod -3,1 = -2,6
Für das Verständnis des folgenden Terms habe ich schon ein bisschen länger gebraucht. Aber meiner Ansicht nach muss der Restwert immer das Vorzeichen der Zahl haben und nicht das Vorzeichen des Divisors:
8,8 mod -3,1 = 2,6

Leider kommen einige Programmiersprachen oder Rechenprogramme nicht zu meinen Schlüssen. Um es kurz zu machen:
Meiner Meinung sind:
- calc.exe auf WinXP
- bc auf Solaris 8
- awk auf Solaris 8
- javascript (mit Gleitkommafehler!)
Nicht meiner Meinung sind:
- MS Excel 2002
- GNU C++ auf Solaris
- Perl 5 auf Solaris
- Caché Object Script

Zumindest bei Excel liegt es daran, dass bei der Berechnung des Restwerts intern offensichtlich die GANZZAHL()-Funktion aus Excel benutzt wird. Ich würde den Rest wiefolgt ausrechnen:
a mod b = a - int( a / b ) * b

... wobei int() die Ganzzahl liefern soll. Zum Beispiel: int(8,8) = 8. Aber hier liegt der Hund begraben: Was ist die Ganzzahl von "-2,8"? "-2" oder "-3"? Excel meint nämlich "-3" und kommt aufgrund dessen auf ein anderes Ergebnis bei der Modulo-Berechnung. Bitte ausprobieren mit =REST(8,8;-3,1)

Apropos Versuche: Am Schluss dieses Posts ist eine Liste der Programmiersprachen und Rechenprogramme, die ich im Moment zur Hand habe. Für Programme, die sich weigern, den Restwert für Kommazahlen auszurechnen, habe ich Natürliche Zahlen gekommen. Außerdem existiert die int()-Funktion nicht überall.
Ich will jeden aufrufen, der Lust dazu hat, meinen Test in anderen Programmiersprachen und Rechenprogrammen durchzuführen und hier zu posten. Wäre interessant, was dabei rauskommt...

Gruß,

notoxp

Code:
Program/Language      OS            a      b     a mod b   int(a)   int(b)
--------------------------------------------------------------------------
bc                    Solaris 8     8,8    3,1    2,6
bc                    Solaris 8     8,8   -3,1    2,6
bc                    Solaris 8    -8,8    3,1   -2,6
bc                    Solaris 8    -8,8   -3,1   -2,6
MS Excel 2002         WinXP         8,8    3,1    2,6      8        3
MS Excel 2002         WinXP         8,8   -3,1   -0,5      8       -4	
MS Excel 2002         WinXP        -8,8    3,1    0,5     -9        3	
MS Excel 2002         WinXP        -8,8   -3,1   -2,6     -9       -4	
calc.exe 5.1          WinXP         8,8    3,1    2,6      8        3	
calc.exe 5.1          WinXP         8,8   -3,1    2,6      8       -3	
calc.exe 5.1          WinXP        -8,8    3,1   -2,6     -8        3	
calc.exe 5.1          WinXP        -8,8   -3,1   -2,6     -8       -3	
perl 5.005            Solaris 8     8,8    3,1    2        8        3
perl 5.005            Solaris 8     8,8   -3,1   -1        8       -3
perl 5.005            Solaris 8    -8,8    3,1    1       -8        3
perl 5.005            Solaris 8    -8,8   -3,1   -2       -8       -3
javascript@IE6        WinXP         8,8    3,1    2,6
javascript@IE6        WinXP         8,8   -3,1    2,6
javascript@IE6        WinXP        -8,8    3,1   -2,6
javascript@IE6        WinXP        -8,8   -3,1   -2,6
gcc 3.3.2             Solaris 8     8      3      2
gcc 3.3.2             Solaris 8     8     -3      2
gcc 3.3.2             Solaris 8    -8      3     -2
gcc 3.3.2             Solaris 8    -8     -3     -2
bash 2.03             Solaris 8     8      3      2
bash 2.03             Solaris 8     8     -3      2
bash 2.03             Solaris 8    -8      3     -2
bash 2.03             Solaris 8    -8     -3     -2
ksh (Korn-Shell)      Solaris 8     8,8    3,1    2        8        3
ksh (Korn-Shell)      Solaris 8     8,8   -3,1    2        8       -3
ksh (Korn-Shell)      Solaris 8    -8,8    3,1   -2       -8        3
ksh (Korn-Shell)      Solaris 8    -8,8   -3,1   -2       -8       -3
awk                   Solaris 8     8,8    3,1    2,6      8        3
awk                   Solaris 8     8,8   -3,1    2,6      8       -3
awk                   Solaris 8    -8,8    3,1   -2,6     -8        3
awk                   Solaris 8    -8,8   -3,1   -2,6     -8       -3
Caché Object Script   WinXP         8,8    3,1    2,6      8        3
Caché Object Script   WinXP         8,8   -3,1   -0,5      8       -3
Caché Object Script   WinXP        -8,8    3,1    0,5     -8        3
Caché Object Script   WinXP        -8,8   -3,1   -2,6     -8       -3
Natural 6.1.1         Solaris/XP    8,8    3,1    0        8        3
Natural 6.1.1         Solaris/XP    8,8   -3,1    0        8       -3
Natural 6.1.1         Solaris/XP   -8,8    3,1    0       -8        3
Natural 6.1.1         Solaris/XP   -8,8   -3,1    0       -8       -3
 
A

Anonymous

Gast
Die Modulo-Funktion ist definiert mit:
Code:
a mod b = a - (b * int(a/b))
das hast du ja auch so gesehen, aber das Problem ist die Definition von int()

Streng gesehen ist die Funktion int() nicht der ganzzahlige Anteil ihres Operanden, sondern die größte Ganze Zahl, die kleiner als der Operand oder gleich dem Operanden ist.

also int (-8.8 ) = -9

Dieses Problem ist aber schon lange bekannt und es ist nun mal so, dass in einigen Fällen die Modulo-Funktion nicht korrekt implementiert ist und in Wirklichkeit den Absolutbetrag vom Divisionsrest liefert. Man stolpert jedochin der Praxis nicht allzuoft über die Auswirkungen. Ein sehr bekanntes Problem ist aber zB die Gaußsche Kalenderformel und das Datum 1. März 2000 das so auf einen Donnerstag errechnet wird ( statt richtigerweise auf Mittwoch)
Ob es jedoch hier an dieser Stelle Sinn macht sich tiefgründig damit zu befassen. ????


robi
 

TeXpert

Guru
Tiefgründig hin oder her, mathematisch betrachet basiert modulo ja schließlich auf der Kongruenzrelation a ~ b (mod m) und hierbei gilt IIRC m \in N, so dass das Ergbnis immer >=0 sein muss ;)
Bei der Definition von a und b bin ich mir jetzt nicht sicher, aber IIRC können die auch aus dem Ring R sein, so dass auch floats möglich sind...

(OK, schlagt mich, ich weiß, dass R nicht nur ein Ring sondern auch ein Körper ist aber Ring reicht IIRC für die Kongruenzen)
 
OP
regexer

regexer

Advanced Hacker
TeXpert schrieb:
so dass das Ergbnis immer >=0 sein muss ;)
Hmmm, vielleicht verstehe ich dich falsch, aber warum sollte das Ergebnis von -5 mod 2 positiv sein? In diesem Falle lägen ja alle oben genannten Sprachen/Programme falsch...
 

TeXpert

Guru
Weil es um Restklassen geht, Zahlentheorie ;)

aber bevor ich mir jetzt die Finger wundschreibe ;) schicke ich Dich mal zur Wikipedia: http://de.wikipedia.org/wiki/Kongruenz_(Zahlentheorie) da ist das ganz gut erklärt... richtig interessant wird der Einsatz dann im Chinesischen Restklassensatz, den brauchst Du sptätenstens dann, wenn Du RSA richtig verstehen willst...
 
OP
regexer

regexer

Advanced Hacker
notoxp schrieb:
Ich will jeden aufrufen, der Lust dazu hat, meinen Test in anderen Programmiersprachen und Rechenprogrammen durchzuführen und hier zu posten. Wäre interessant, was dabei rauskommt...
Ich ergänze:
Code:
Program/Language      OS            a      b     a mod b   int(a)   int(b) 
-------------------------------------------------------------------------- 
python 2.4            SLES 9        8,8    3,1    2,6      8        3
python 2.4            SLES 9        8,8   -3,1   -0,5      8       -3
python 2.4            SLES 9       -8,8    3,1    0,5     -8        3
python 2.4            SLES 9       -8,8   -3,1    2,6     -8       -3
gcc 3.3.5             SLES 9        8      3      2
gcc 3.3.5             SLES 9        8     -3      2
gcc 3.3.5             SLES 9       -8      3     -2
gcc 3.3.5             SLES 9       -8     -3     -2
bc 1.06               SLES 9        8,8    3,1    2,6
bc 1.06               SLES 9        8,8   -3,1    2,6
bc 1.06               SLES 9       -8,8    3,1   -2,6
bc 1.06               SLES 9       -8,8   -3,1   -2,6
perl 5.8.6            SLES 9        8,8    3,1    2        8        3
perl 5.8.6            SLES 9        8,8   -3,1   -1        8       -3
perl 5.8.6            SLES 9       -8,8    3,1    1       -8        3
perl 5.8.6            SLES 9       -8,8   -3,1   -2       -8       -3
bash 3.00.16          SLES 9        8      3      2 
bash 3.00.16          SLES 9        8     -3      2 
bash 3.00.16          SLES 9       -8      3     -2 
bash 3.00.16          SLES 9       -8     -3     -2 
gawk 3.1.4            SLES 9        8,8    3,1    2,6      8        3
gawk 3.1.4            SLES 9        8,8   -3,1    2,6      8       -3
gawk 3.1.4            SLES 9       -8,8    3,1   -2,6     -8        3
gawk 3.1.4            SLES 9       -8,8   -3,1   -2,6     -8       -3
 
Oben