Saya mencoba mod integer untuk mendapatkan posisi array sehingga akan diulang. Melakukan i %
arrayLength
berfungsi baik untuk angka positif tetapi untuk angka negatif semuanya salah.
4 % 3 == 1
3 % 3 == 0
2 % 3 == 2
1 % 3 == 1
0 % 3 == 0
-1 % 3 == -1
-2 % 3 == -2
-3 % 3 == 0
-4 % 3 == -1
jadi saya butuh implementasi
int GetArrayIndex(int i, int arrayLength)
seperti yang
GetArrayIndex( 4, 3) == 1
GetArrayIndex( 3, 3) == 0
GetArrayIndex( 2, 3) == 2
GetArrayIndex( 1, 3) == 1
GetArrayIndex( 0, 3) == 0
GetArrayIndex(-1, 3) == 2
GetArrayIndex(-2, 3) == 1
GetArrayIndex(-3, 3) == 0
GetArrayIndex(-4, 3) == 2
Saya sudah melakukan ini sebelumnya tetapi untuk beberapa alasan itu melelehkan otak saya hari ini :(
Jawaban:
Saya selalu menggunakan
mod
fungsi saya sendiri , didefinisikan sebagaiTentu saja, jika Anda merasa perlu dua panggilan ke operasi modulus, Anda dapat menuliskannya sebagai
atau varian daripadanya.
Alasannya adalah karena "x% m" selalu dalam kisaran [-m + 1, m-1]. Jadi, jika semuanya negatif, menambahkan m akan menempatkannya dalam kisaran positif tanpa mengubah nilainya modulo m.
sumber
r = x%m
adalah-1
, setelahr+m
itu1
. Loop sementara tidak diperlukan. Intinya adalah bahwa (seperti yang saya tulis dalam jawaban),x%m
selalu benar-benar lebih besar daripada-m
, jadi Anda perlu menambahkanm
paling banyak satu kali untuk membuatnya positif.r
untuka
modulob
, maka itu adalah sedemikian sehingga 0 ≤ r <| b |.Harap dicatat bahwa% operator C # dan C ++ sebenarnya BUKAN modulo, itu tetap. Rumus untuk modulo yang Anda inginkan, dalam kasus Anda, adalah:
Anda harus mengode ulang ini dalam C # (atau C ++) tetapi ini adalah cara Anda mendapatkan modulo dan bukan sisanya.
sumber
-21 mod 4 is 3 because -21 + 4 x 6 is 3.
Tetapi-21 divided by 4 gives -5
dengan aremainder of -1
. Untuk nilai positif, tidak ada perbedaan. Jadi tolong informasikan diri Anda tentang perbedaan-perbedaan ini. Dan jangan percaya Wikipedia setiap saat :)%
sisanya?Implementasi single-line
%
hanya menggunakan sekali:sumber
mod(-10, 6)
dengan tangan, Anda bisa menambah atau mengurangi 6 berulang-ulang sampai jawabannya ada dalam kisaran[0, 6)
. Notasi ini berarti "inklusif di sebelah kiri, dan eksklusif di sebelah kanan". Dalam kasus kami, kami menambahkan 6 dua kali, memberi 2. Kode ini cukup sederhana, dan mudah untuk melihat bahwa itu benar: pertama, itu sama dengan menambahkan / mengurangin
seperti di atas, kecuali bahwa itu berhenti satun
pendek, jika mendekati dari sisi negatifnya. Dalam hal ini kami memperbaikinya. Ada: komentar :)%
mungkin ide yang bagus. Lihat tabel Biaya apa saja dalam kode terkelola di artikel Menulis Kode Terkelola Lebih Cepat: Mengetahui Apa Harganya . Penggunaannya%
sama mahal dengan yangint div
tercantum dalam tabel: sekitar 36 kali lebih mahal daripada menambah atau mengurangi, dan sekitar 13 kali lebih mahal daripada mengalikan. Tentu saja, bukan masalah besar kecuali ini adalah inti dari apa yang dilakukan kode Anda.%
lebih mahal daripada tes dan lompatan, terutama jika itu tidak mudah diprediksi?Jawaban ShreevatsaR tidak akan berfungsi untuk semua kasus, bahkan jika Anda menambahkan "jika (m <0) m = -m;", jika Anda memperhitungkan dividen / pembagi negatif.
Sebagai contoh, -12 mod -10 akan menjadi 8, dan seharusnya -2.
Implementasi berikut akan bekerja untuk dividen / pembagi positif dan negatif dan sesuai dengan implementasi lain (yaitu, Java, Python, Ruby, Scala, Skema, Javascript dan Kalkulator Google):
Test suite menggunakan xUnit:
sumber
mod
fungsi biasanya disebut dengan modulus positif (perhatikan variabelarrayLength
dalam pertanyaan asli yang dijawab di sini, yang mungkin tidak pernah negatif), sehingga fungsi tersebut tidak perlu dibuat untuk bekerja untuk modulus negatif. (Itulah sebabnya saya menyebut perlakuan modulus negatif dalam komentar atas jawaban saya, bukan dalam jawaban itu sendiri.) (Lanjutan ...)r = a - b floor(a/b)
selalu positif). Bahkan di antara sistem komputer, Pascal dan Maple misalnya, mendefinisikannya selalu positif.Menambah pengertian.
Menurut definisi Euclidean hasil mod harus selalu positif.
Ex:
Keluaran:
sumber
-1
?the positive remainder is always chosen
,, tetapi bahasa pemrograman memilih tergantung pada bahasa dan tanda-tanda a dan / atau n. [5] Standard Pascal dan Algol68 memberikan sisa positif (atau 0) bahkan untuk pembagi negatif, dan beberapa bahasa pemrograman, seperti C90, serahkan saja pada implementasi ketika salah satu dari atau negatif adalah '.Membandingkan dua jawaban utama
dan
Tidak ada yang benar-benar menyebutkan fakta bahwa yang pertama mungkin melempar
OverflowException
sementara yang kedua tidak. Lebih buruk lagi, dengan konteks tidak dicentang default, jawaban pertama dapat mengembalikan jawaban yang salah (lihatmod(int.MaxValue - 1, int.MaxValue)
misalnya). Jadi jawaban kedua sepertinya tidak hanya lebih cepat, tetapi juga lebih tepat.sumber
Cukup tambahkan modulus Anda (arrayLength) ke hasil negatif dari% dan Anda akan baik-baik saja.
sumber
Untuk para pengembang yang lebih sadar kinerja
Perbandingan kinerja kecil
Adapun biaya kinerja pemain untuk Anda lihat di sini
sumber
-3 % 10
seharusnya -3 atau 7. Karena hasil yang tidak negatif diinginkan, 7 akan menjadi jawabannya. Implementasi Anda mengembalikan 3. Anda harus mengubah kedua parameter keuint
dan menghapus gips.n
merupakan kekuatan dua, dalam hal ini Anda cukup menggunakan logika dan ((uint)k & (n - 1)
) sebagai gantinya, jika kompiler belum melakukannya untuk Anda (kompiler sering kali cukup pintar untuk mengetahui hal ini).Saya suka trik yang disajikan oleh Peter N Lewis di utas ini : "Jika n memiliki rentang terbatas, maka Anda bisa mendapatkan hasil yang Anda inginkan hanya dengan menambahkan kelipatan [pembagi] konstan yang diketahui yang lebih besar daripada nilai absolut dari minimum."
Jadi jika saya memiliki nilai d yaitu dalam derajat dan saya ingin mengambil
dan saya ingin menghindari masalah jika d negatif, maka saya hanya melakukan ini:
Ini mengasumsikan bahwa meskipun d mungkin negatif, diketahui bahwa ia tidak akan pernah lebih negatif dari -720.
sumber
%
.Anda mengharapkan perilaku yang bertentangan dengan perilaku yang didokumentasikan dari operator% di c # - mungkin karena Anda mengharapkannya bekerja dengan cara yang berfungsi dalam bahasa lain yang Anda lebih terbiasa. The dokumentasi pada negara-negara c # (penekanan):
Nilai yang Anda inginkan dapat dihitung dengan satu langkah ekstra:
sumber
Penerapan satu baris jawaban dcastro (paling sesuai dengan bahasa lain):
Jika Anda ingin tetap menggunakan
%
operator (Anda tidak dapat membebani operator asli di C #):Gunakan kasing, keduanya berfungsi:
sumber
Semua jawaban di sini berfungsi dengan baik jika pembagi Anda positif, tetapi tidak cukup lengkap. Berikut ini adalah implementasi saya yang selalu mengembalikan pada kisaran
[0, b)
, sehingga tanda keluaran sama dengan tanda pembagi, memungkinkan pembagi negatif sebagai titik akhir untuk rentang keluaran.PosMod(5, 3)
pengembalian2
PosMod(-5, 3)
pengembalian1
PosMod(5, -3)
pengembalian-1
PosMod(-5, -3)
pengembalian-2
(di mana
real_t
bisa menjadi jenis nomor apa saja)sumber