Znalazłem dziwne zachowanie w Pythonie dotyczące liczb ujemnych:
>>> -5 % 4
3
Czy ktoś mógłby wyjaśnić, co się dzieje?
python
modulo
negative-number
facha
źródło
źródło
..., -9, -5, -1, 3, 7, ...
math.fmod
aby uzyskać takie samo zachowanie, jak w C lub Javie.Odpowiedzi:
W przeciwieństwie do C i C ++, operator modulo (
%
) w Pythonie zawsze zwraca liczbę mającą ten sam znak co mianownik (dzielnik). Twoje wyrażenie daje 3, ponieważJest wybierany zamiast zachowania C, ponieważ wynik nieujemny jest często bardziej przydatny. Przykładem jest obliczenie dni tygodnia. Jeśli dzisiaj jest wtorek (dzień # 2), jaki jest dzień tygodnia N dni wcześniej? W Pythonie możemy obliczać z
return (2 - N) % 7
ale w C, jeśli N ≥ 3, otrzymujemy liczbę ujemną, która jest liczbą nieprawidłową i musimy to naprawić ręcznie, dodając 7:
int result = (2 - N) % 7; return result < 0 ? result + 7 : result;
(Zobacz http://en.wikipedia.org/wiki/Modulo_operator, aby dowiedzieć się, jak znak wyniku jest określany w różnych językach).
źródło
Oto wyjaśnienie Guido van Rossuma:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
Zasadniczo jest tak, że a / b = q z resztą r zachowuje relacje b * q + r = a i 0 <= r <b.
źródło
a
, pozytywówb
, podczas gdy Python jest piętrem. To zawsze prawdaabs(r) < b
, a oni nie mogąr <= 0
.Nie ma jednego najlepszego sposobu obsługi dzielenia liczb całkowitych i modów z liczbami ujemnymi. Byłoby miło, gdyby
a/b
była ta sama wielkość i przeciwny znak(-a)/b
. Byłoby miło, gdybya % b
rzeczywiście był modulo b. Ponieważ naprawdę tego chcemya == (a/b)*b + a%b
, pierwsze dwa są niekompatybilne.Które zachować, to trudne pytanie i istnieją argumenty dla obu stron. C i C ++ zaokrąglają dzielenie liczb całkowitych do zera (tak
a/b == -((-a)/b)
), a Python najwyraźniej tego nie robi.źródło
Jak wskazano, Python modulo stanowi uzasadniony wyjątek od konwencji innych języków.
Daje to liczbom ujemnym płynne zachowanie, szczególnie w połączeniu z
//
operatorem dzielenia liczby całkowitej, jak%
to często bywa w przypadku modulo (jak w matematyce. Divmod ):for n in range(-8,8): print n, n//4, n%4
Produkuje:
-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
%
zawsze wyświetla zero lub dodatnie *//
zawsze zaokrągla w kierunku ujemnej nieskończoności* ... o ile właściwy operand jest dodatni. Z drugiej strony
11 % -10 == -9
źródło
W Pythonie operator modulo działa w ten sposób.
>>> mod = n - math.floor(n/base) * base
więc wynik jest (dla twojego przypadku):
mod = -5 - floor(-1.25) * 4 mod = -5 - (-2*4) mod = 3
podczas gdy inne języki, takie jak C, JAVA, JavaScript używają obcinania zamiast floor.
>>> mod = n - int(n/base) * base
Co skutkuje w:
mod = -5 - int(-1.25) * 4 mod = -5 - (-1*4) mod = -1
Jeśli potrzebujesz więcej informacji o zaokrąglaniu w Pythonie, przeczytaj to .
źródło
Modulo, klasy równoważności dla 4:
Oto link do zachowania modulo z liczbami ujemnymi . (Tak, wygooglowałem to)
źródło
Pomyślałem też, że to dziwne zachowanie Pythona. Okazuje się, że nie rozwiązałem dobrze podziału (na papierze); Podawałem ilorazowi wartość 0, a pozostałej - -5. Okropne ... Zapomniałem o geometrycznej reprezentacji liczb całkowitych. Przywołując geometrię liczb całkowitych podaną przez oś liczbową, można uzyskać prawidłowe wartości ilorazu i reszty oraz sprawdzić, czy zachowanie Pythona jest w porządku. (Chociaż zakładam, że już dawno rozwiązałeś swój problem).
źródło
Warto też wspomnieć, że również podział w pythonie jest inny niż w C: Consider
>>> x = -10 >>> y = 37
w C spodziewasz się wyniku
0
co to jest x / y w Pythonie?
>>> print x/y -1
a% to modulo - nie reszta! Podczas gdy x% y w C daje
-10
Python daje.
>>> print x%y 27
Możesz uzyskać oba jak w C.
Dywizja:
>>> from math import trunc >>> d = trunc(float(x)/y) >>> print d 0
A reszta (stosując podział z góry):
>>> r = x - d*y >>> print r -10
To obliczenie może nie jest najszybsze, ale działa dla dowolnej kombinacji znaków x i y, aby osiągnąć takie same wyniki, jak w C, a ponadto unika instrukcji warunkowych.
źródło