В java, когда вы делаете
a % b
Если a отрицательно, он вернет отрицательный результат, вместо того, чтобы оборачиваться до b, как должно. Как лучше всего это исправить? Я могу думать только так
a < 0 ? b + a : a % b
В java, когда вы делаете
a % b
Если a отрицательно, он вернет отрицательный результат, вместо того, чтобы оборачиваться до b, как должно. Как лучше всего это исправить? Я могу думать только так
a < 0 ? b + a : a % b
Он ведет себя так, как должен a% b = a - a / b * b; т.е. это остаток.
Вы можете сделать (a% b + b)% b
Это выражение работает, поскольку результат (a % b)
обязательно ниже, чем b
, независимо от того, положительный или отрицательный a
. Добавление b
учитывает отрицательные значения a
, поскольку (a % b)
является отрицательным значением между -b
и 0
, (a % b + b)
обязательно ниже b
и положительно. Последний модуль присутствует в случае, если a
был положительным с самого начала, поскольку, если a
положителен, (a % b + b)
станет больше, чем b
. Следовательно, (a % b + b) % b
снова превращает его в меньшее, чем b
(и не влияет на отрицательные a
значения).
(a % b)
обязательно ниже, чем b
(независимо от того, является ли a
положительным или отрицательным), добавление b
учитывает отрицательные значения a
, поскольку (a % b)
ниже b
и ниже 0
, (a % b + b)
обязательно ниже, чем b
и положительно. Последний модуль присутствует в случае, если a
был положительным с самого начала, поскольку, если a
положителен, (a % b + b)
станет больше, чем b
. Следовательно, (a % b + b) % b
снова превращает его в меньшее, чем b
(и не влияет на отрицательные a
значения).
- person ethanfar; 13.04.2014
a < 0
, может быть, вы могли бы взглянуть)
- person Maarten Bodewes; 13.09.2014
(a % b + b) % b
не работает при очень больших значениях a
и b
. Например, использование a = Integer.MAX_VALUE - 1
и b = Integer.MAX_VALUE
даст результат -3
, что является отрицательным числом, чего вы хотели избежать.
- person Thorbear; 16.09.2015
(a % b + b) % b
не намного медленнее, чем a = a % b; while (a < 0) { a += b;}
? Поскольку вам нужно выполнить две операции по модулю? (Предполагая, что вас интересуют только случаи, когда a ‹= b)
- person Mikepote; 08.03.2016
while
, будет медленнее, если он вам действительно нужен, за исключением того, что вам нужен только if
, и в этом случае он действительно быстрее.
- person Peter Lawrey; 08.03.2016
hashCode
метод String возвращает отрицательное значение bcoz, из которого мое значение индекса становится отрицательным. Я хотел посмотреть, сможешь ли ты помочь.
- person arsenal; 19.04.2016
-1 div 4 = -1
вместо -1 / 4 = 0
)? Вот он (при условии, что у вас уже есть модуль в переменной mod_ab
): (a - (mod_ab - a % b)) / b
.
- person Rômulo Ceccon; 17.03.2017
a
находится на b
расстоянии от 0
(например, при переносе экрана некоторой обновленной координаты x a
на 2D-карту игры шириной b
), (a + b) % b
подойдет.
- person runcoderun; 17.10.2018
Начиная с Java 8, вы можете использовать Math.floorMod (int x, int y) и Math.floorMod (long x, long y). Оба эти метода возвращают те же результаты, что и ответ Питера.
Math.floorMod( 2, 3) = 2
Math.floorMod(-2, 3) = 1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2
float
или double
аргументами. Бинарный оператор Mod (%
) также работает с операндами float
и double
.
- person Mir-Ismaili; 07.06.2018
Тем, кто еще не использует (или не может использовать) Java 8, на помощь приходит Guava с IntMath.mod (), доступный с Guava 11.0.
IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1
Одно предостережение: в отличие от Java 8 Math.floorMod (), делитель (второй параметр) не может быть отрицательным.
В теории чисел результат всегда положительный. Я предполагаю, что это не всегда так в компьютерных языках, потому что не все программисты математики. Мои два цента, я бы посчитал это конструктивным дефектом языка, но вы не можете его сейчас изменить.
= МОД (-4,180) = 176 = МОД (176, 180) = 176
потому что 180 * (-1) + 176 = -4 то же самое, что 180 * 0 + 176 = 176
Используя здесь пример часов, http://mathworld.wolfram.com/Congruence.html вы бы не говорите, что duration_of_time mod cycle_length составляет -45 минут, вы бы сказали 15 минут, даже если оба ответа удовлетворяют базовому уравнению.
-1
вместо n-1
), тогда действуйте.
- person BeUndead; 10.07.2019
В 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
.
Вот альтернатива:
a < 0 ? b-1 - (-a-1) % b : a % b
Это может быть или не быть быстрее, чем другая формула [(a% b + b)% b]. В отличие от другой формулы, она содержит ветвь, но использует на одну операцию по модулю меньше. Вероятно, выигрыш, если компьютер сможет правильно предсказать <0.
(Изменить: исправлена формула.)