Dalam program C saya mencoba operasi di bawah ini (Hanya untuk memeriksa perilaku)
x = 5 % (-3);
y = (-5) % (3);
z = (-5) % (-3);
printf("%d ,%d ,%d", x, y, z);
memberi saya output seperti (2, -2 , -2)
dalam gcc. Saya mengharapkan hasil yang positif setiap saat. Bisakah modulus menjadi negatif? Adakah yang bisa menjelaskan perilaku ini?
Jawaban:
C99 mensyaratkan bahwa ketika
a/b
representable:(a/b) * b
+a%b
harus samaa
Ini masuk akal, secara logis. Baik?
Mari kita lihat apa yang menyebabkan hal ini:
Contoh A.
5/(-3)
adalah-1
=>
(-1) * (-3)
+5%(-3)
=5
Ini hanya dapat terjadi jika
5%(-3)
2.Contoh B.
(-5)/3
adalah-1
=>
(-1) * 3
+(-5)%3
=-5
Ini hanya dapat terjadi jika
(-5)%3
ada-2
sumber
-5/3
adalah-2
dan mod menjadi 1. Singkatnya: satu modul memiliki tanda yang mengikuti tanda dividen (terpotong), modul lainnya memiliki tanda yang mengikuti tanda pembagi (Knuth).The
%
operator dalam C bukan modulo Operator tapi sisanya operator.Modulo dan operator lainnya berbeda dalam hal nilai negatif.
Dengan operator sisa, tanda hasilnya sama dengan tanda dividen sementara dengan operator modulo tanda hasilnya sama dengan pembagi.
C mendefinisikan
%
operasi untuka % b
sebagai:dengan
/
divisi integer dengan pemotongan menuju0
. Itu pemotongan yang dilakukan terhadap0
(dan bukan menuju inifinity negatif) yang mendefinisikan%
sebagai operator sisa daripada operator modulo.sumber
remainder
danmodulo
dalam Skema,rem
danmod
dalam Haskell). Spesifikasi operator ini berbeda pada bahasa ini tentang cara pembagian dilakukan: pemotongan menuju 0 atau ke arah infinity negatif. Dengan cara C Standar tidak pernah menyebut%
para operator yang Modulo , mereka hanya nama itu yang Operator% .remainder
fungsi dalam C, yang mengimplementasikan sisa IEEE dengan semantik bulat-ke-terdekat di divisiBerdasarkan Spesifikasi C99:
a == (a / b) * b + a % b
Kita dapat menulis fungsi untuk menghitung
(a % b) == a - (a / b) * b
!Untuk operasi modulo, kita dapat memiliki fungsi berikut (dengan asumsi
b > 0
)Kesimpulan saya adalah bahwa
a % b
dalam C adalah operasi sisa dan BUKAN operasi modulo.sumber
b
negatif (dan pada kenyataannya untukr
danb
keduanya negatif memberikan hasil kurang dari-b
). Untuk memastikan hasil positif untuk semua input yang dapat Anda gunakanr + abs(b)
atau untuk mencocokkanb
dengan tanda, Anda dapat mengubah kondisir*b < 0
.r + abs(b)
adalah UB kapanb == INT_MIN
.Saya tidak berpikir tidak perlu memeriksa apakah angkanya negatif.
Fungsi sederhana untuk menemukan modulo positif adalah ini -
Edit: Dengan asumsi
N > 0
danN + N - 1 <= INT_MAX
Ini akan bekerja untuk nilai x positif dan negatif .
PS asli: juga seperti yang ditunjukkan oleh @chux, Jika x dan N Anda masing-masing dapat mencapai sesuatu seperti INT_MAX-1 dan INT_MAX, cukup ganti
int
denganlong long int
.Dan Jika mereka melewati batas yang lama juga (yaitu dekat LLONG_MAX), maka Anda harus menangani kasus positif dan negatif secara terpisah seperti yang dijelaskan dalam jawaban lain di sini.
sumber
N < 0
, hasilnya mungkin negatif seperti padamodulo(7, -3) --> -2
. Jugax % N + N
bisa meluapint
matematika yang merupakan perilaku yang tidak terdefinisi. misalnyamodulo(INT_MAX - 1,INT_MAX)
bisa menghasilkan -3.long long int
, atau menangani kasus negatif secara terpisah (dengan biaya kehilangan kesederhanaan).Jawaban lain telah dijelaskan dalam C99 atau lebih baru, pembagian bilangan bulat yang melibatkan operan negatif selalu terpotong ke nol .
Perhatikan bahwa, dalam C89 , apakah hasil putaran ke atas atau ke bawah ditentukan oleh implementasi. Karena
(a/b) * b + a%b
samaa
di semua standar, hasil dari%
melibatkan operan negatif juga implementasi-didefinisikan dalam C89.sumber
%
bisa negatif karena ini adalah operator sisa , sisanya setelah pembagian, bukan setelah Euclidean_division . Sejak C99 hasilnya mungkin 0, negatif atau positif.The modulo OP ingin adalah klasik modulo Euclidean , tidak
%
.Untuk melakukan modulo Euclidean yang terdefinisi dengan baik kapan pun
a/b
didefinisikan,a,b
adalah dari tanda apa pun dan hasilnya tidak pernah negatif:sumber
Hasil operasi Modulo tergantung pada tanda pembilang, sehingga Anda mendapatkan -2 untuk y dan z
Inilah rujukannya
http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_14.html
sumber
Dalam Matematika, di mana konvensi ini berasal, tidak ada pernyataan bahwa modulo aritmatika harus menghasilkan hasil yang positif.
Misalnya.
1 mod 5 = 1, tetapi bisa juga sama dengan -4. Yaitu, 1/5 menghasilkan sisa 1 dari 0 atau -4 dari 5. (Kedua faktor 5)
Demikian pula, -1 mod 5 = -1, tetapi bisa juga sama dengan 4. Yaitu, -1/5 menghasilkan sisa -1 dari 0 atau 4 dari -5. (Kedua faktor 5)
Untuk bacaan lebih lanjut, lihatlah ke kelas ekivalensi dalam Matematika.
sumber
a
danb
,b <> 0
. Menurut teorema pembagian Euclidean ada persis sepasang sepasang bilangan bulatm
, dir
manaa = m * b + r
dan0 <= r < abs( b )
. Kata tersebutr
adalah hasil dari operasi modulo (matematis) dan menurut definisi tidak negatif. Lebih banyak bacaan dan tautan lebih lanjut di Wikipedia: en.wikipedia.org/wiki/Euclidean_division1 mod 5
selalu 1.-4 mod 5
mungkin 1 juga, tetapi mereka adalah hal yang berbeda.Menurut standar C99 , bagian 6.5.5 Operator penggandaan , yang berikut ini diperlukan:
Kesimpulan
Tanda hasil dari operasi sisa, menurut C99, sama dengan tanda dividen.
Mari kita lihat beberapa contoh (
dividend / divisor
):Ketika hanya dividen yang negatif
Ketika hanya pembagi yang negatif
Ketika kedua pembagi dan dividen negatif
sumber
Operator modulus memberikan sisanya. Operator modulus dalam c biasanya mengambil tanda pembilang
Juga operator modulus (sisa) hanya dapat digunakan dengan tipe integer dan tidak dapat digunakan dengan floating point.
sumber
Saya percaya ini lebih berguna untuk dipikirkan
mod
karena didefinisikan dalam aritmatika abstrak; bukan sebagai operasi, tetapi sebagai kelas aritmatika yang berbeda, dengan elemen yang berbeda, dan operator yang berbeda. Itu berarti penambahan dalammod 3
tidak sama dengan penambahan "normal"; itu adalah; penambahan bilangan bulat.Jadi ketika Anda melakukannya:
Anda mencoba memetakan bilangan bulat 5 ke elemen di set
mod -3
. Ini adalah elemen darimod -3
:Begitu:
Katakanlah Anda harus begadang karena sesuatu alasan 30 jam, berapa jam lagi yang tersisa untuk hari itu?
30 mod -24
.Tetapi apa yang tidak diterapkan oleh C
mod
, itu adalah sisa. Bagaimanapun, intinya adalah masuk akal untuk mengembalikan negatif.sumber