2012-04-08 12 views
6

cercato attraverso altre risposte e io continuo a non capire il modulo per i numeri negativi in ​​pythonModulo per i dividendi negativi in ​​Python

Per esempio la risposta df

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

quindi ha senso che (-2)% 5 = -2 - (-2/5) * 5 = 3

Non questo (-2 - (-2/5) * 5) = 0 o sono solo pazzo? Modulus operation with negatives values - weird thing?

Stessa cosa con questo negative numbers modulo in python Dove ha trovato -2 da?

Infine, se il segno dipende dal dividendo perché i dividendi negativi non hanno lo stesso risultato delle controparti positive?

Ad esempio l'uscita di

print([8%5,-8%5,4%5,-4%5]) 

è

[3, 2, 4, 1] 
+0

È possibile utilizzare 'math.fmod' per ottenere lo stesso comportamento di C o Java. – Helio

risposta

9

In Python, modulo viene calcolato secondo due modalità:

  • (a // b) * b + (a % b) == a e
  • a % b ha lo stesso segno b.

Combina questo con il fatto che la divisione intera arrotonda verso il basso (verso -∞) e viene spiegato il comportamento risultante.

Se si esegue -8 // 5, si ottiene -1,6 arrotondato per difetto, ovvero -2. Moltiplica quello per 5 e ottieni -10; 2 è il numero che dovresti aggiungere a quello per ottenere -8. Pertanto, -8 % 5 è 2.

0

Quando si divide interi (-2/5) * 5 fa non restituiscono -2, come sarebbe nel algebra a cui sei abituato. Prova a scomporlo in due passaggi, valutando prima la parte tra parentesi.

  1. (-2/5) * 5 = (-1) * 5
  2. (-1) * 5 = -5

La ragione per la fase 1 è che si sta facendo int division, che in python 2.x restituisce l'equivalente del risultato della divisione float arrotondato all'intero più vicino.

In python 3 e versioni successive, 2/5 restituirà un valore float, vedere PEP 238.

0

Verificare this BetterExplained article e guardare il commento di David (n. 6) per ottenere ciò di cui gli altri stanno parlando.

Dal momento che stiamo lavorando w/interi, facciamo divisione int, che, in Python, piani la risposta al contrario di C. Per ulteriori informazioni su questo leggi Guido's article.

Per quanto riguarda la tua domanda:

>>> 8 % 5 #B'coz (5*1) + *3* = 8 
3 
>>> -8 % 5 #B'coz (5*-2) + *2* = -8 
2 

Speranza che ha aiutato. Mi ha confuso anche all'inizio (lo fa ancora)! :)

3

La logica alla base di questa è in realtà la definizione matematica di least residue. Python rispetta questa definizione, mentre nella maggior parte degli altri linguaggi di programmazione l'operatore modulo è in realtà più simile a un operatore di "reaminder after division". Per calcolare il minimo residuo di -5 % 11, è sufficiente aggiungere 11 a -5 fino ad ottenere un numero intero positivo nell'intervallo [0,10], e il risultato è 6.

5

In Python, a // b è definito come piano (a/b), come contrario alla maggior parte delle altre lingue in cui la divisione intera è definita come trunc (a/b). C'è una differenza corrispondente nell'interpretazione di a % b = a - (a // b) * b.

Il ragione di questo è che la definizione di Python del % dell'operatore (e divmod) è generalmente più utile rispetto a quella di altre lingue. Per esempio:

def time_of_day(seconds_since_epoch): 
    minutes, seconds = divmod(seconds_since_epoch, 60) 
    hours, minutes = divmod(minutes, 60) 
    days, hours = divmod(hours, 24) 
    return '%02d:%02d:%02d' % (hours, minutes, seconds) 

Con questa funzione, time_of_day(12345) rendimenti '03:25:45', come ci si aspetterebbe.

Ma che ore sono 12345 secondi prima del l'epoca? Con la definizione di Python divmod, time_of_day(-12345) restituisce correttamente '20:34:15'.

E se ridefinire divmod per utilizzare la definizione C di / e %?

def divmod(a, b): 
    q = int(a/b) # I'm using 3.x 
    r = a - b * q 
    return (q, r) 

Ora, time_of_day(-12345) rendimenti '-3:-25:-45', che non è un tempo di validità del giorno. Se la funzione standard Python divmod fosse implementata in questo modo, dovresti scrivere codice di caso speciale per gestire gli input negativi. Ma con la divisione in stile piano, come il mio primo esempio, funziona semplicemente.

+1

Ho usato Python solo un po 'e non ne sono rimasto colpito, ma mi scalda il cuore nel vedere almeno un linguaggio di programmazione che si presta a un operatore di divisione utilizzabile. Il tuo esempio di ora del giorno è fantastico. Ho visto lamentele sul fatto che un operatore del modulo Euclideo non lavori per estrarre cifre da numeri negativi (ad esempio -123% 10 rese 7 anche se l'ultima cifra è 3). D'altra parte, un operatore di resto del tipo C che produce -3 non è davvero migliore. – supercat

Problemi correlati