В 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
значения).a < 0
, может быть, вы могли бы взглянуть)(a % b + b) % b
распадается на очень большие значенияa
иb
. Например, использованиеa = Integer.MAX_VALUE - 1
иb = Integer.MAX_VALUE
даст в-3
качестве результата отрицательное число, чего вы хотели избежать.while
будет медленнее, если он вам действительно нужен, за исключением того, что вам нужен только, иif
в этом случае он действительно быстрее.Начиная с Java 8, вы можете использовать Math.floorMod (int x, int y) и Math.floorMod (long x, long y) . Оба эти метода возвращают те же результаты, что и ответ Питера.
источник
float
илиdouble
аргументами. Mod бинарный оператор (%
) также работает сfloat
иdouble
операнды.Для тех, кто еще не использует (или не может использовать) Java 8, Guava пришел на помощь с IntMath.mod () , доступным с Guava 11.0.
Одно предостережение: в отличие от 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
например) тогда займись этим.В Java 8 есть
Math.floorMod
, но он очень медленный (в его реализации есть несколько делений, умножений и условное выражение). Вполне возможно, что JVM имеет внутреннюю оптимизированную заглушку для нее, однако, что значительно ускорит ее.Самый быстрый способ обойтись без этого
floorMod
- как и некоторые другие ответы здесь, но без условных переходов и только с одной медленной%
операцией.Предполагая, что n положительно, а x может быть любым:
Результаты при
n = 3
:Если вам нужно только равномерное распределение между
0
и,n-1
а не точным оператором мода, и ваши операторыx
не сгруппированы рядом0
, следующее будет еще быстрее, так как параллелизм на уровне инструкций больше, и медленные%
вычисления будут происходить параллельно с другим частей, поскольку они не зависят от его результата.return ((x >> 31) & (n - 1)) + (x % n)
Результаты для вышеуказанного с
n = 3
:Если вход является случайным во всем диапазоне int, распределение обоих двух решений будет одинаковым. Если входные кластеры близки к нулю,
n - 1
в последнем решении будет слишком мало результатов .источник
Вот альтернатива:
Это может быть или не быть быстрее, чем другая формула [(a% b + b)% b]. В отличие от другой формулы, она содержит ветвь, но использует на одну операцию по модулю меньше. Вероятно, выигрыш, если компьютер сможет правильно предсказать <0.
(Изменить: исправлена формула.)
источник