Java 8 имеет Math.floorMod
, но это очень медленно (его реализация имеет несколько делений, умножений и условных выражений).Вполне возможно, что JVM имеет встроенную оптимизированную заглушку, что значительно ускорит ее.
Самый быстрый способ сделать это без floorMod
подобен некоторым другим ответам здесь, но без условных переходови только один медленный %
op.
Предполагается, что n положительно, а x может быть любым:
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;
Результаты, когда n = 3
:
x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
0| 0
1| 1
2| 2
3| 0
4| 1
Если вам нужно только равномерное распределение между 0
и n-1
, а не точный оператор мода, и ваши x
не кластеризуются вблизи 0
, следующее будет еще быстрее, так как есть больше инструкцийпараллелизм уровня и медленное вычисление %
будут происходить параллельно с другими частями, поскольку они не зависят от его результата.
return ((x >> 31) & (n - 1)) + (x % n)
Результаты для вышеупомянутого с 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
Если входной сигнал является случайным во всем диапазоне int, распределениеоба решения будут одинаковыми.Если входные кластеры близки к нулю, в последнем решении будет слишком мало результатов при n - 1
.