Python'da negatif sayılarla ilgili bazı garip davranışlar buldum:
>>> -5 % 4
3
Biri neler olduğunu açıklayabilir mi?
Python'da negatif sayılarla ilgili bazı garip davranışlar buldum:
>>> -5 % 4
3
Biri neler olduğunu açıklayabilir mi?
..., -9, -5, -1, 3, 7, ...
math.fmod
C veya Java'daki ile aynı davranışı elde etmek için kullanabilirsiniz .
Yanıtlar:
C veya C ++ 'dan farklı olarak, Python'un modulo operatörü ( %
) her zaman payda (bölen) ile aynı işarete sahip bir sayı döndürür. İfadeniz 3 verir çünkü
(-5) / 4 = -1,25 -> kat (-1,25) = -2
(-5)% 4 = (-2 × 4 + 3)% 4 = 3.
Negatif olmayan bir sonuç genellikle daha yararlı olduğu için C davranışı yerine seçilir. Bir örnek, hafta içi günleri hesaplamaktır. Bugün Salı ise (2. gün), N gün öncesindeki hafta içi gün nedir? Python'da hesaplayabiliriz
return (2 - N) % 7
ancak C'de, N ≥ 3 ise, geçersiz bir sayı olan negatif bir sayı elde ederiz ve bunu 7 ekleyerek manuel olarak düzeltmemiz gerekir:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
( Farklı diller için sonuç işaretinin nasıl belirlendiğini öğrenmek için http://en.wikipedia.org/wiki/Modulo_operator adresine bakın .)
İşte Guido van Rossum'dan bir açıklama:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
Esasen, kalan r ile a / b = q, b * q + r = a ve 0 <= r <b ilişkilerini korur.
a
, pozitif b
, oysa Python tabanları için sona erer . Bu her zaman doğrudur abs(r) < b
ve onlar sona erer r <= 0
.
Negatif sayılarla tamsayı bölmesini ve modları ele almanın en iyi yolu yoktur. a/b
Aynı büyüklükte ve zıt işaretli olsaydı güzel olurdu (-a)/b
. a % b
Gerçekten de bir modulo olsaydı iyi olurdu b. Gerçekten istediğimiz a == (a/b)*b + a%b
için ilk ikisi uyumsuzdur.
Hangisini saklamak zor bir soru ve her iki taraf için de tartışmalar var. C ve C ++ yuvarlak tamsayı bölümü sıfıra doğru (yani a/b == -((-a)/b)
) ve görünüşe göre Python değil.
Belirtildiği gibi, Python modulo , diğer dillerin gelenekleri için iyi gerekçeli bir istisna yapar .
Bu, negatif sayılara, özellikle //
tamsayı bölme operatörü ile birlikte kullanıldığında, modulo'nun%
sıklıkla olduğu gibi (math. Divmod'da olduğu gibi ) sorunsuz bir davranış sağlar :
for n in range(-8,8):
print n, n//4, n%4
Üretir:
-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
%
her zaman sıfır veya pozitif çıktı *//
her zaman negatif sonsuzluğa yuvarlanır* ... sağ operand pozitif olduğu sürece. Diğer yandan11 % -10 == -9
In piton , modülo operatörü bu gibi çalışır.
>>> mod = n - math.floor(n/base) * base
yani sonuç (sizin durumunuz için):
mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3
oysa C, JAVA, JavaScript gibi diğer diller floor yerine kısaltma kullanır.
>>> mod = n - int(n/base) * base
sonuç:
mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1
Eğer python yuvarlama hakkında daha fazla bilgi gerekiyorsa, okuma bu .
Modulo, 4 için eşdeğerlik sınıfları:
İşte modulonun negatif sayılarla davranışına bir bağlantı . (Evet, Google'da araştırdım)
Ayrıca Python'un garip bir davranışı olduğunu düşündüm. Bölmeyi iyi çözemediğim ortaya çıktı (kağıt üzerinde); Bölüme 0 değeri ve kalanına -5 değeri veriyordum. Korkunç ... Tam sayıların geometrik temsilini unuttum. Sayı doğrusu tarafından verilen tamsayıların geometrisini hatırlayarak, bölüm ve kalan bölüm için doğru değerler elde edilebilir ve Python'un davranışının iyi olup olmadığı kontrol edilebilir. (Endişenizi uzun süre önce çözdüğünüzü varsaymama rağmen).
Ayrıca python'daki bölünmenin de C'den farklı olduğunu belirtmekte fayda var:
>>> x = -10
>>> y = 37
C'de sonucu bekliyorsun
0
python'da x / y nedir?
>>> print x/y
-1
ve% modulo'dur - geri kalan değil! C veriminde x% y ise
-10
python verimi.
>>> print x%y
27
İkisini de C'deki gibi alabilirsin
Bölme:
>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0
Ve geri kalanı (yukarıdan bölümü kullanarak):
>>> r = x - d*y
>>> print r
-10
Bu hesaplama belki en hızlısı değildir, ancak C'deki ile aynı sonuçları elde etmek için x ve y'nin herhangi bir işaret kombinasyonu için çalışır, artı koşullu ifadelerden kaçınır.