Java 8 memiliki Math.floorMod
, tetapi sangat lambat (implementasinya memiliki beberapa divisi, perkalian, dan bersyarat). Mungkin saja JVM memiliki rintisan yang dioptimalkan secara intrinsik untuknya, bagaimanapun, yang akan mempercepatnya secara signifikan.
Cara tercepat untuk melakukan ini tanpanya floorMod
adalah seperti beberapa jawaban lain di sini, tetapi tanpa cabang bersyarat dan hanya satu %
operasi lambat .
Asumsi n positif, dan x bisa berupa apa saja:
int remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;
Hasil ketika n = 3
:
x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
0| 0
1| 1
2| 2
3| 0
4| 1
Jika Anda hanya memerlukan distribusi seragam antara 0
dan n-1
dan bukan operator mod yang tepat, dan Anda x
tidak mengelompokkan dekat 0
, berikut ini akan menjadi lebih cepat, karena ada lebih banyak paralelisme tingkat instruksi dan %
komputasi lambat akan terjadi secara paralel dengan yang lain bagian karena tidak bergantung pada hasilnya.
return ((x >> 31) & (n - 1)) + (x % n)
Hasil diatas dengan n = 3
:
x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
0| 0
1| 1
2| 2
3| 0
4| 1
5| 2
Jika masukan acak dalam rentang penuh int, distribusi kedua solusi akan sama. Jika cluster masukan mendekati nol, akan ada terlalu sedikit hasil di n - 1
solusi terakhir.