2010-10-07 18 views
39

ho trovato un po 'strano comportamento in Python per quanto riguarda i numeri negativi:L'operazione di modulo sui numeri negativi in ​​Python

>>> a = -5 
>>> a % 4 
3 

Qualcuno potrebbe spiegare che cosa sta succedendo?

+14

mi sembra giusto – wheaties

+3

'..., -9, -5, -1, 3, 7, ...' – NullUserException

+0

possibile duplicato di [C, Python - comportamento diverso dell'operazione modulo (%)] (http://stackoverflow.com/questions/1907565/c-python-different-behaviour-of-the-modulo-operation) – nyuszika7h

risposta

68

A differenza di C o C++, l'operatore modulo Python (%) restituisce sempre un numero con lo stesso segno del denominatore (divisore). Proprie rese espressione 3 perché

(-5)% 4 = (-2 × 4 + 3)% 4 = 3.

Viene scelta sul comportamento C perché un risultato negativo è spesso più utile. Un esempio è quello di calcolare i giorni della settimana. Se oggi è martedì (giorno 2), qual è il giorno della settimana N giorni prima? In Python possiamo calcolare con

return (2 - N) % 7 

ma in C, se N ≥ 3, otteniamo un numero negativo che è un numero non valido, e occorre fissare manualmente con l'aggiunta di 7:

int result = (2 - N) % 7; 
return result < 0 ? result + 7 : result; 

(Vedi http://en.wikipedia.org/wiki/Modulo_operator per come il segno del risultato è determinato per le diverse lingue.)

+1

Non dovrebbe essere (-2 * 4 + 3)? – Vatine

+0

@Vatine: risolto grazie. (Stavo pensando a 5 ^^) – kennytm

+0

Come si emula questo utilissimo operatore in C/C++? –

2

Modulo, classi di equivalenza per 4:

  • 0: 0, 4, 8, 12 ... e -4, -8, -12 ...
  • 1: 1, 5, 9, 13 ... e -3, -7, -11 ...
  • 2: 2, 6, 10 ... e -2, -6, -10 ...
  • 3: 3, 7, 11 ... e -1, -5, -9 ...

Ecco un collegamento a modulo's behavior with negative numbers. (Sì, l'ho cercato su google)

+0

@NullUserException - sì, lo era. fisso. Grazie. – wheaties

7

Non esiste un modo migliore per gestire la divisione integer e le mod con numeri negativi. Sarebbe bello se a/b fosse la stessa grandezza e il segno opposto di (-a)/b. Sarebbe bello se a % b fosse effettivamente un modulo b. Dal momento che vogliamo veramente a == (a/b)*b + a%b, i primi due sono incompatibili.

Quale da tenere è una domanda difficile, e ci sono argomenti per entrambe le parti. Divisione intera di C e C++ intorno a zero (quindi a/b == -((-a)/b)) e apparentemente Python no.

2

Come indicato, il modulo Python crea un'eccezione well-reasoned alle convenzioni di altre lingue. Ciò conferisce ai numeri negativi un comportamento senza interruzioni, specialmente se utilizzato in combinazione con l'operatore di divisione intero //, poiché il modulo % è spesso (come in matematica.divmod):

for n in range(-8,8): 
    print n, n//4, n%4 

produce:

-8 -2 0 
-7 -2 1 
-6 -2 2 
-5 -2 3 

-4 -1 0 
-3 -1 1 
-2 -1 2 
-1 -1 3 

    0 0 0 
    1 0 1 
    2 0 2 
    3 0 3 

    4 1 0 
    5 1 1 
    6 1 2 
    7 1 3 
+0

Grazie al tuo esempio mi hai fatto capire :) – Lamis

1

ho anche pensato che fosse uno strano comportamento di Python. Si scopre che non stavo risolvendo bene la divisione (sulla carta); Stavo dando un valore di 0 al quoziente e un valore di -5 al resto. Terribile ... Ho dimenticato la rappresentazione geometrica dei numeri interi. Richiamando la geometria degli interi forniti dalla linea numerica, si possono ottenere i valori corretti per il quoziente e il resto, e controllare che il comportamento di Python sia corretto. (Anche se presumo che tu abbia già risolto la tua preoccupazione molto tempo fa).

Problemi correlati