web-dev-qa-db-fra.com

À Scala, pourquoi l'opérateur restant (%) pourrait-il retourner un nombre négatif?

Par exemple, (-3) % 2 Renverra -1 Au lieu de 1.

Quelle est la meilleure façon d'obtenir le reste positif à Scala? Tels que (((-3) % 2) + 2) % 2 Ou abs(-3 % 2)?

17
Hanfei Sun

En scala, pourquoi l'opérateur restant (%) pourrait-il retourner un nombre négatif?

Il existe différentes conventions pour le signe du résultat d'une opération modulo; Wikipedia a un bon article dessus . Scala, comme la plupart, mais en aucun cas tous les langages de programmation, a le résultat prendre le signe du dividende (le -3 Dans votre cas).

Quelle est la meilleure façon d'obtenir le reste positif à Scala?

Je doute qu'il existe une méthode préférée généralement acceptée; si c'était moi, utilisez soit Math.floorMod , ce qui donne un résultat avec le signe du diviseur (2 dans votre exemple) au lieu du dividende (cela ne fait pas ' t signifie simplement la même valeur que % avec un signe différent, voir JavaDoc lié pour plus de détails). Ou juste un if après (if (result < 0) { result += M; } [où M est le diviseur, 2 Dans votre exemple]).

15
T.J. Crowder

La bonne façon d'obtenir le module positif est d'ajouter le diviseur au module négatif:

(-18 % 5) + 5

Prendre la valeur absolue vous donnera la mauvaise solution dans ce cas, mais cela fonctionnera si le diviseur se trouve être 2.

Si vous ne connaissez pas le signe du dividende, vous pouvez faire quelque chose comme ceci:

((dividend % divisor) + divisor) % divisor
12
Kevin

Je voudrais ajouter quelque chose aux réponses existantes. Ma façon préférée d'obtenir le reste positif est d'ajouter une nouvelle méthode au type Int comme suit:

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

Dans le fichier où vous souhaitez utiliser la méthode, importez la classe implicite avec:

import Extensions._

Vous pouvez maintenant:

(-3).positiveMod(2)

Vous pouvez également placer la classe implicite dans un objet de package afin que vous n'ayez pas besoin d'importer lors de l'appel de la fonction à partir du même package.

2
user42723

L'utilisation de math.abs(-x % y) ne donne généralement pas le même comportement que le retour d'un module positif:

scala> math.abs(-7 % 3)
res46: Int = 1

Mais ce n'est pas ce que python (un langage qui retourne un module positif) dit:

In [14]: -7 % 3
Out[14]: 2

Si nous regardons les incréments de 3 de -7:

-7, -4, -1, 2, ..

scala s'arrête à -1 et python s'arrête à 2.

2
Akavall