В scala, почему оператор остатка (%) возвращает отрицательное число?
Например, (-3) % 2
вернет -1
вместо 1
.
Каков предпочтительный способ получить положительный остаток в Scala? Например, (((-3) % 2) + 2) % 2
или abs(-3 % 2)
?
Ответы
Ответ 1
В scala, почему оператор остатка (%) возвращает отрицательное число?
Существуют различные соглашения для знака результата операции по модулю; В Википедии есть хорошая статья об этом. scala, как и большинство, но далеко не все языки программирования, результат принимает знак дивиденда (-3
в вашем случае).
Каков предпочтительный способ получить положительный остаток в Scala?
Я сомневаюсь, что в общем согласен предпочтительный способ; если бы это был я, используйте Math.floorMod
, который дает результат со знаком делителя (2
в вашем примере) вместо дивиденда (это doesn 't означает только то же значение, что и %
с другим знаком, см. связанный JavaDoc для деталей). Или просто if
после (if (result < 0) { result += M; }
[где M
- это делитель, 2
в вашем примере]).
Ответ 2
Правильный способ получить положительный модуль - добавить делитель к отрицательному модулю:
(-18 % 5) + 5
Принимая абсолютное значение, вы получите неправильное решение в этом случае, хотя оно будет работать, если делитель окажется равным 2.
Если вы не знаете знака дивиденда, вы можете сделать что-то вроде этого:
((dividend % divisor) + divisor) % divisor
Ответ 3
Использование math.abs(-x % y)
обычно не дает такого же поведения, как возврат положительного модуля:
scala> math.abs(-7 % 3)
res46: Int = 1
Но не то, что питон (язык, который возвращает положительный модуль) говорит:
In [14]: -7 % 3
Out[14]: 2
Если мы посмотрим на приращения 3 от -7:
-7, -4, -1, 2, ..
scala
останавливается на -1
, а python
останавливается на 2
.
Ответ 4
Я хотел бы добавить что-то к существующим ответам. Мой предпочтительный способ получить положительный остаток - добавить новый метод к типу Int следующим образом:
object Extensions
{
implicit class ExtendedInt (val i: Int) extends AnyVal {
def positiveMod (m: Int) = {val x = i % m; if (x < 0) x + m else x}
}
}
В файле, где вы хотите использовать метод, импортируйте неявный класс с помощью:
import Extensions._
Теперь вы можете сделать:
(-3).positiveMod(2)
Вы также можете поместить неявный класс в объект пакета, поэтому вам не нужно импортировать его при вызове функции из того же пакета.
Ответ 5
Например, если вы хотите отфильтровать все нечетные элементы из массива, игнорируя отрицательные или положительные значения, вы можете сделать так:
arr.filter {x = > Math.abs(x% 2) == 1}