Saya telah menemukan beberapa perilaku aneh dengan Python terkait bilangan negatif:
>>> -5 % 4
3
Adakah yang bisa menjelaskan apa yang sedang terjadi?
Saya telah menemukan beberapa perilaku aneh dengan Python terkait bilangan negatif:
>>> -5 % 4
3
Adakah yang bisa menjelaskan apa yang sedang terjadi?
..., -9, -5, -1, 3, 7, ...
math.fmod
untuk mendapatkan perilaku yang sama seperti di C atau Java.
Jawaban:
Tidak seperti C atau C ++, operator modulo Python ( %
) selalu mengembalikan angka yang memiliki tanda yang sama dengan penyebut (pembagi). Ekspresi Anda menghasilkan 3 karena
(-5) / 4 = -1,25 -> lantai (-1,25) = -2
(-5)% 4 = (-2 × 4 + 3)% 4 = 3.
Ini dipilih daripada perilaku C karena hasil nonnegatif seringkali lebih berguna. Contohnya adalah menghitung hari kerja. Jika hari ini adalah Selasa (hari # 2), apakah hari kerja N hari sebelumnya? Dengan Python kita bisa menghitung dengan
return (2 - N) % 7
tetapi di C, jika N ≥ 3, kita mendapatkan angka negatif yang merupakan angka yang tidak valid, dan kita perlu memperbaikinya secara manual dengan menambahkan 7:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(Lihat http://en.wikipedia.org/wiki/Modulo_operator untuk mengetahui bagaimana tanda hasil ditentukan untuk bahasa yang berbeda.)
Berikut penjelasan dari Guido van Rossum:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
Pada dasarnya, a / b = q dengan sisa r mempertahankan hubungan b * q + r = a dan 0 <= r <b.
a
, positif b
, sedangkan Python floor. Itu selalu benar abs(r) < b
, dan mereka berhenti r <= 0
.
Tidak ada satu cara terbaik untuk menangani pembagian integer dan mod dengan bilangan negatif. Alangkah baiknya jika a/b
besarnya sama dan tanda berlawanan (-a)/b
. Alangkah baiknya jika a % b
memang sebuah modulo b. Karena kami benar-benar ingin a == (a/b)*b + a%b
, dua yang pertama tidak cocok.
Yang mana yang harus disimpan adalah pertanyaan yang sulit, dan ada argumen untuk kedua belah pihak. Pembagian integer bulat C dan C ++ menuju nol (jadi a/b == -((-a)/b)
), dan ternyata Python tidak.
Seperti yang ditunjukkan, Python modulo membuat pengecualian yang beralasan untuk konvensi bahasa lain.
Ini memberikan bilangan negatif perilaku yang mulus, terutama bila digunakan dalam kombinasi dengan //
operator integer-divide, seperti yang %
sering dilakukan modulo (seperti dalam math. Divmod ):
for n in range(-8,8):
print n, n//4, n%4
Menghasilkan:
-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
%
selalu menghasilkan nol atau positif *//
selalu membulatkan ke arah negatif tak terhingga* ... selama operan kanannya positif. Di samping itu11 % -10 == -9
Di python , operator modulo bekerja seperti ini.
>>> mod = n - math.floor(n/base) * base
jadi hasilnya adalah (untuk kasus Anda):
mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3
sedangkan bahasa lain seperti C, JAVA, JavaScript menggunakan pemotongan, bukan floor.
>>> mod = n - int(n/base) * base
yang mengakibatkan:
mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1
Jika Anda memerlukan informasi lebih lanjut tentang pembulatan dengan python, baca ini .
Modulo, kelas kesetaraan untuk 4:
Berikut link ke perilaku modulo dengan bilangan negatif . (Ya, saya mencarinya di Google)
Saya juga berpikir itu adalah perilaku aneh Python. Ternyata saya tidak menyelesaikan pembagian dengan baik (di atas kertas); Saya memberikan nilai 0 untuk hasil bagi dan nilai -5 untuk sisanya. Mengerikan ... Saya lupa representasi geometris dari bilangan bulat. Dengan mengingat geometri bilangan bulat yang diberikan oleh garis bilangan, seseorang bisa mendapatkan nilai yang benar untuk hasil bagi dan sisanya, dan memeriksa apakah perilaku Python baik-baik saja. (Meskipun saya berasumsi bahwa Anda telah menyelesaikan masalah Anda sejak lama).
Perlu juga disebutkan bahwa pembagian python juga berbeda dari C: Pertimbangkan
>>> x = -10
>>> y = 37
di C Anda mengharapkan hasilnya
0
apa x / y dengan python?
>>> print x/y
-1
dan% adalah modulo - bukan sisanya! Sedangkan x% y di C. menghasilkan
-10
python menghasilkan.
>>> print x%y
27
Anda bisa mendapatkan keduanya seperti di C
Divisi:
>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0
Dan sisanya (menggunakan pembagian dari atas):
>>> r = x - d*y
>>> print r
-10
Penghitungan ini mungkin bukan yang tercepat tetapi berfungsi untuk kombinasi tanda apa pun dari x dan y untuk mencapai hasil yang sama seperti di C plus, ini menghindari pernyataan bersyarat.