В 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}