Znalazłem dziwne zachowanie w Pythonie dotyczące liczb ujemnych:
>>> -5 % 4
3
Czy ktoś mógłby wyjaśnić, co się dzieje?
Znalazłem dziwne zachowanie w Pythonie dotyczące liczb ujemnych:
>>> -5 % 4
3
Czy ktoś mógłby wyjaśnić, co się dzieje?
..., -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ż
(-5) / 4 = -1,25 -> podłoga (-1,25) = -2
(-5)% 4 = (-2 × 4 + 3)% 4 = 3.
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).
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.
a
, pozytywów b
, podczas gdy Python jest piętrem. To zawsze prawda abs(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, gdyby a % b
rzeczywiście był modulo b. Ponieważ naprawdę tego chcemy a == (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.
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 strony11 % -10 == -9
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 .
Modulo, klasy równoważności dla 4:
Oto link do zachowania modulo z liczbami ujemnymi . (Tak, wygooglowałem to)
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).
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.