
Μπορείτε σας παρακαλώ να μου πείτε πόσο είναι `(-2) % 5`; Σύμφωνα με την Python διερμηνέα μου είναι 3, αλλά έχετε μια σοφή εξήγηση γι 'αυτό;


Έχω διαβάσει ότι σε ορισμένες γλώσσες το αποτέλεσμα μπορεί να είναι το μηχάνημα που εξαρτώνται, αλλά δεν είμαι σίγουρος όμως.

 
Μέτρο συνεργασία με αρνητικά τις τιμές - παράξενο πράγμα;
=========================================================



Με την ευκαιρία: οι περισσότερες γλώσσες προγραμματισμού, θα διαφωνήσω με Python και να δώσει το αποτέλεσμα `-2`. Ανάλογα με την ερμηνεία του συντελεστή αυτό είναι σωστό. Ωστόσο, το πιο συμφωνημένη μαθηματική κράτη ορισμό ότι το μέτρο της *α* και *β* είναι το (αυστηρά θετικό) υπόλοιπο *r* της διαίρεσης του *ενός* / *b* . Ακριβέστερα, 0 <= *r* < *b* εξ ορισμού.

 

Ο ερμηνευτής Python σας είναι σωστή. Ένα (ηλίθιος) τρόπος υπολογισμού ενός συντελεστή είναι να αφαιρέσει ή να προσθέσει το μέτρο μέχρις ότου η προκύπτουσα τιμή είναι μεταξύ 0 και (μέτρο - 1).


π.χ: 13 mod 5 = (13 - 5) mod 5 = (13 - 10) mod 5 = 3


ή στην περίπτωσή σας: -2 mod 5 = (-2 + 5) mod 5 = 3

 

Λοιπόν, -2 διαιρείται με 5 θα είναι 0 με ένα υπόλοιπο 3. Δεν πιστεύω ότι πρέπει να είναι πολύ πλατφόρμα που εξαρτώνται, αλλά έχω δει περίεργα πράγματα.

 

Είναι πράγματι 3. Στο [modular αριθμητική](http://en.wikipedia.org/wiki/Modular_arithmetic) , ένας συντελεστής είναι απλώς το υπόλοιπο μιας διαίρεσης, και το υπόλοιπο των -2 διαιρείται με 5 είναι 3.

 

Το αποτέλεσμα της πράξης μέτρο για αρνητικά φαίνεται να είναι γλώσσα προγραμματισμού που εξαρτάται και εδώ είναι μια λίστα <http://en.wikipedia.org/wiki/Modulo_operation>

 

Λοιπόν, 0% 5 θα πρέπει να είναι 0, έτσι δεν είναι;


-1% 5 θα πρέπει να είναι 4, επειδή αυτό είναι το επόμενο επιτρέπεται ψηφίο πηγαίνει προς την αντίθετη κατεύθυνση (δηλαδή, δεν μπορεί να είναι 5, δεδομένου ότι είναι εκτός εμβέλειας).


Και μετά μαζί με αυτή τη λογική, -2 πρέπει να είναι 3.


Ο ευκολότερος τρόπος για να σκεφτούμε πώς θα λειτουργήσει είναι ότι θα κρατήσει προσθέτοντας ή αφαιρώντας 5 έως ότου ο αριθμός κυμαίνεται μεταξύ 0 (συμπεριλαμβανομένου) και 5 (αποκλειστικά).


Δεν είμαι σίγουρος για την εξάρτηση της μηχανής - Δεν έχω δει ποτέ μια εφαρμογή που ήταν, αλλά δεν μπορώ να πω ότι ποτέ δεν έχει κάνει.

 

Το αποτέλεσμα εξαρτάται από τη γλώσσα. Python επιστρέφει το σημείο του διαιρέτη, όπου για παράδειγμα c # επιστρέφει το σήμα του μερίσματος (δηλ. -2% 5 επιστρέφει -2 σε C #).

 

Μια εξήγηση μπορεί να είναι ότι οι αρνητικοί αριθμοί αποθηκεύονται χρησιμοποιώντας [το συμπλήρωμα 2 του](http://en.wikipedia.org/wiki/Two%27s_complement) . Όταν ο διερμηνέας python προσπαθεί να κάνει τη λειτουργία modulo το μετατρέπει σε ανυπόγραφο αξία. Ως εκ τούτου, αντί να κάνει (-2)% 5 να υπολογίζει στην πραγματικότητα 0xFFFF\_FFFF\_FFFF\_FFFD% 5 η οποία είναι 3.

 

Όπως εξήγησε σε άλλες απαντήσεις, υπάρχουν πολλές επιλογές για μια λειτουργία modulo με αρνητικές τιμές. Σε γενικές γραμμές διαφορετικές γλώσσες (και διαφορετικές πλατφόρμες) θα δώσουν ένα διαφορετικό αποτέλεσμα.


Σύμφωνα με το [εγχειρίδιο αναφοράς Python](http://docs.python.org/ref/binary.html) ,



> 
> Ο χειριστής modulo αποδίδει πάντα ένα αποτέλεσμα με το ίδιο πρόσημο με το δεύτερο τελεστέο της (ή μηδέν)? η απόλυτη τιμή του αποτελέσματος είναι αυστηρά μικρότερη από την απόλυτη τιμή του δεύτερου τελεστή.
> 
> 
> 


είναι η επιλογή που λαμβάνονται από την Python. Βασικά modulo ορίζεται έτσι ώστε αυτό ισχύει πάντα:



```
x == (x/y)*y + (x%y)

```

έτσι είναι λογικό ότι (-2)% 5 = -2 - (-2/5) * 5 = 3

 

Να είστε προσεκτικοί για να μην στηρίζονται σε αυτό το mod συμπεριφορά σε C / C ++ σε όλα τα λειτουργικά συστήματα και αρχιτεκτονικές. Αν θυμάμαι καλά, προσπάθησα να βασίζονται σε C / C ++ κώδικα όπως



```
float x2 = x % n;

```

για να κρατήσει x2 στην περιοχή από 0 έως n-1, αλλά αρνητικοί αριθμοί παρεισφρήσει σε όταν θα καταρτίζουν σε ένα λειτουργικό σύστημα, αλλά τα πράγματα θα δουλεύουν μια χαρά σε ένα άλλο λειτουργικό σύστημα. Αυτό γίνεται για ένα κακό χρόνο εντοπισμού σφαλμάτων, δεδομένου ότι συνέβη μόνο το μισό χρόνο!

 

Όπως και η τεκμηρίωση λέει στο [δυαδικό αριθμητικές πράξεις](http://docs.python.org/reference/expressions.html#binary) , Python διαβεβαιώνει ότι:



> 
> Οι χειριστές ακέραιος διαίρεση και modulo συνδέονται με την ακόλουθη ταυτότητα: `x == (x/y)*y + (x%y)`. Διαίρεση Ακέραιος και modulo συνδέονται επίσης με την ενσωματωμένη λειτουργία divmod (): `divmod(x, y) == (x/y, x%y)`.
> 
> 
> 


Και πραγματικά,



```
>>> divmod(-2, 5)
(-1, 3).

```

Ένας άλλος τρόπος για να απεικονίσει την ομοιομορφία της μεθόδου αυτής είναι να υπολογίσει `divmod`μια μικρή ακολουθία αριθμών:



```
>>> for number in xrange(-10, 10):
...     print divmod(number, 5)
...
(-2, 0)
(-2, 1)
(-2, 2)
(-2, 3)
(-2, 4)
(-1, 0)
(-1, 1)
(-1, 2)
(-1, 3)
(-1, 4)
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(1, 4)

```
 

Φαίνεται να υπάρχει ένα κοινό σύγχυση μεταξύ των όρων «modulo» και «υπόλοιπο» εκεί.


Στα μαθηματικά, ένα υπόλοιπο θα πρέπει *πάντα* να ορίζεται σύμφωνα με την πηλίκο, έτσι ώστε αν `a / b == c rem d`στη συνέχεια `(c * b) + d == a`. Ανάλογα με το πώς μπορείτε να στρογγυλοποιεί πηλίκο σας, μπορείτε να πάρετε διάφορα υπολείμματα.


Ωστόσο, modulo πρέπει πάντα να δίνουν ένα αποτέλεσμα `0 <= r < divisor`, που συνάδει μόνο με διαίρεση γύρο-με-μείον-άπειρο, αν επιτρέπετε αρνητικοί ακέραιοι. Εάν διαίρεση στρογγυλοποιεί προς το μηδέν (η οποία είναι κοινή), modulo και υπόλοιπα είναι μόνο ισοδύναμες για μη αρνητικές τιμές.


Μερικές γλώσσες (κυρίως C και C ++) δεν καθορίζουν τις απαιτούμενες / υπόλοιπο συμπεριφορές στρογγυλοποίησης και `%`είναι διφορούμενη. Πολλοί ορίζουν στρογγυλοποίησης ως προς το μηδέν, αλλά χρησιμοποιούν τον όρο modulo όπου υπόλοιπο θα ήταν πιο σωστό. Python είναι σχετικά ασυνήθιστο σε ότι γύρους σε αρνητικό άπειρο, έτσι modulo και τα λοιπά είναι ισοδύναμα.


Ada γύρους προς το μηδέν IIRC, αλλά έχει και τα δύο `mod`και `rem`φορείς.


Η πολιτική C έχει ως στόχο να επιτρέψει μεταγλωττιστές για να επιλέξετε την πιο αποτελεσματική εφαρμογή για το μηχάνημα, αλλά ΙΜΟ είναι μια ψεύτικη βελτιστοποίησης, τουλάχιστον αυτές τις μέρες. Ένα καλό compiler κατά πάσα πιθανότητα θα είναι σε θέση να χρησιμοποιήσει την ισοδυναμία για τη βελτιστοποίηση όπου ένας αρνητικός αριθμός δεν μπορεί να συμβεί (και σχεδόν σίγουρα, αν χρησιμοποιείτε ανυπόγραφο είδη). Από την άλλη πλευρά, όπου μπορεί να συμβεί αρνητικούς αριθμούς, που είναι σχεδόν βέβαιο ότι ενδιαφέρονται για τις λεπτομέρειες - για λόγους φορητότητας θα πρέπει να χρησιμοποιήσετε πολύ προσεκτικά σχεδιασμένο overcomplex αλγόριθμους ή / και ελέγχους για να διασφαλίσει ότι θα έχετε τα αποτελέσματα που θέλετε, ανεξάρτητα από τη στρογγυλοποίηση και λοιπά η ΣΥΜΠΕΡΙΦΟΡΑ.


Με άλλα λόγια, το κέρδος για αυτήν την «βελτιστοποίηση» είναι κυρίως (αν όχι πάντα) μια ψευδαίσθηση, ενώ υπάρχουν πολύ πραγματικό κόστος σε ορισμένες περιπτώσεις - γι 'αυτό είναι μια λανθασμένη βελτιστοποίησης.

 