JavaScript, % (modulo) donne un résultat négatif pour les nombres négatifs
Selon Google Calculatrice (-13) % 64
est 51
.
Selon Javascript (voir ce JSBin) il est -13
.
Comment puis-je résoudre ce problème?
- Cela peut juste être une question de priorité. Voulez-vous dire
(-13) % 64
ou-(13 % 64)
? Personnellement, je l'avais mis dans les parens de toute façon, juste pour plus de clarté. - édité, merci.
- essentiellement une copie de Comment java module de calculs avec des nombres négatifs? même si c'est un javascript question.
- Javascript se sent parfois comme une plaisanterie cruelle
- google ne peut pas être mauvais
- Le problème fondamental est en JS
%
n'est pas l'opérateur modulo. C'est le reste de l'opérateur. Il n'y a pas d'opérateur modulo en JavaScript. Si l'on a accepté la réponse est le chemin à parcourir. - Lequel avez-vous l'intention de corriger, Google ou JS?
Vous devez vous connecter pour publier un commentaire.
Prises à partir de cet article: Le JavaScript Modulo Bug
x < -n
- par exemple(-7 + 5) % 5 === -2
mais((-7 % 5) + 5) % 5 == 3
.Number.prototype.mod
n'a pas d'effet dans les navigateurs modernes - au moins Firefox 28, Chrome 32.(-13).mod(64)
et obtenir51
. jsfiddle.net/63KyCNumber.prototype.myfunction = ...
-1 modulo 12
est de 11, mais-1 % 12
est -1. Elle est tout à fait explicite dans ce §5.2 Algorithme de Conventions où il est dit: "La notation “x modulo y” (y doit être finie et différente de zéro) calcule une valeur k de même signe que y (ou zéro) tels que abs(k) < abs(y) et x-k = q × y pour certaines entier q.", ce qui n'est pas la façon dont le%
opérateur fonctionne.%
est maintenant appelé un MultiplicativeOperator et à l'est par rapport au C et C++ reste de l'opérateur.À l'aide de
Number.prototype
est LENT, parce que chaque fois que vous utilisez la méthode de prototype de votre numéro est enveloppé dans unObject
. Au lieu de cela:Utilisation:
Voir: http://jsperf.com/negative-modulo/2
~97% plus rapide que l'utilisation d'un prototype. Si la performance est importante pour vous, bien sûr..
n
s etm
s dans le mauvais sens dans votre deuxième exemple @StuR . Il devrait êtrereturn ((n % m) + m) % m;
.La
%
opérateur en JavaScript est le reste de l'opérateur, et non pas l'opérateur modulo (la principale différence est dans la façon dont les nombres négatifs sont traités):-1 % 8 // -1, not 7
Un "mod" de la fonction pour retourner un résultat positif.
Et bien sûr
#sec-applying-the-mod-operator
dans l'url 🙂 bref, merci pour la remarque, j'ai pris les peluches de ma réponse, ce n'est pas vraiment important de toute façon.Accepté la réponse me rend un peu nerveux, parce qu'il ré-utilise l'opérateur%. Si Javascript modifie le comportement dans le futur?
Voici une solution de contournement qui n'a pas ré-utiliser %:
-
,*
,/
,;
,.
,(
,)
,,
,Math.floor
,function
oureturn
changements? Ensuite, votre code est horriblement cassé.JavaScript Modulo
Mise en œuvre réussie d'un calcul scientifique ou de l'algorithme est possible non seulement de comprendre les caractéristiques d'un langage ou d'un cadre, mais propose également de comprendre les limites.
Ordinateurs sont précis instruments scientifiques, mais ils travaillent-ils par la manipulation d'entités dans de petits espaces (vous avez un nombre limité de pixels sur l'écran, il y a un nombre limité de bits qui sont derrière chaque numéro, etc.)
Essayer d'ignorer les limites ou le cadre des spécifications et bientôt vous verrez que vous avez une différence d'impédance entre votre formule mathématique et le code que vous essayez d'écrire.
Opérateur Modulo
Parfois, les situations sont compliquées par faussement annoncé ou entendu cadre des fonctions ou opérateurs. Cet article se concentre sur l'opérateur modulo.
Demandez à n'importe quel C# ou JavaScript programmeur quel est l'opérateur modulo dans leur langue et il ya une grande chance qu'ils vont allé réponse: % (par exemple, le signe de pourcentage). L'abondance de la documentation, reportez-vous à la % à l'inscription en tant que opérateur modulo.
Wow! C'est une subtile, mais très dangereuse erreur. En C# et JavaScript opérateur % est actuellement utilisé pour calculer le reste (avec signe) qui reste lorsque l'un des opérandes est divisé par le deuxième opérande. Par conséquent, l'opérande doit être correctement appelé signé le reste de l'opérateur.
À première vue, l'signé le reste de l'opérateur fonctionne de manière similaire à l'opérateur modulo. Nous allons faire quelques tests en comparant les résultats retournés par JavaScript avec ceux retournés par Google.
Dans Chrome, ouvrez la console (appuyez sur la touche F12 et sélectionnez l'onglet de la Console). Type de il y, un par un, les calculs à partir de la colonne de gauche. Tapez ensuite les mêmes expressions dans la barre de recherche de Google. Notez les résultats. Ils devraient être les mêmes.
Nous allons maintenant essayer d'utiliser une valeur négative comme le premier opérande:
Surprise!
-5 % 3 = 1 (selon Google)
-5 % 3 = -2 (selon JavaScript)
Bien ... cela ne devrait pas réellement une surprise si l'on regarde la définition de l'opérateur % en JavaScript (... ou encore C# ou de nombreuses autres langues). Google calcule le vrai modulo, bien que ces langages de calculer un signé de rappel.
Cependant, pas tous les langages de programmation /cadres ont la même mise en œuvre de %. En Python, par exemple, l'opérateur % calcule le vrai modulo de la même manière que Google.
Cette différence de comportement entre les langues peuvent introduire un subtil des erreurs dans votre calcul, surtout si vous essayez de port d'un algorithme à partir d'une langue à l'autre!
Un problème compris, c'est un problème à moitié résolu
Supposons que nous avons besoin pour mettre en œuvre une (scientifique) de calcul en JavaScript en utilisant l'arithmétique modulo.
Puisque nous comprenons maintenant que JavaScript n'est pas un vrai opérateur modulo, nous pouvons facilement mettre en œuvre notre modulo comme une fonction.
Il y a de multiples façons de mettre en œuvre modulo en JavaScript. Je vais vous montrer 3 façons de le faire.
Plus précis sur les outils à notre disposition, nous sommes maintenant prêts à s'attaquer à ce (scientifique) de calcul et de s'attendre à obtenir de bons résultats à chaque fois.
Remarque: Il y a beaucoup de calculs qui font usage de l'arithmétique modulo... Si vous voulez voir comment utiliser ces nouvelles modulo les fonctions dans la mise en œuvre d'un César de Chiffrement /ROT13 code, vous pouvez vérifier ce l'article.
Si elle n'est pas se comporter comme prévu, cela ne signifie pas que le JavaScript n'est pas 'comportement'. C'est un choix JavaScript pour son calcul modulo. Parce que, par définition, soit de répondre de sens.
Voir cette à partir de Wikipedia. Vous pouvez voir sur la droite comment les différentes langues ont choisi le résultat du signe.
Si
x
est un entier etn
est une puissance de 2, vous pouvez utiliserx & (n - 1)
au lieu dex % n
.Il semble donc que si vous essayez de mod autour de degrés (de sorte que si vous avez -50 degrés - 200 degrés), vous voulez utiliser quelque chose comme:
Je traite avec un négatif et négatif n trop
Ce n'est pas un bug, il y a 3 fonctions pour calculer modulo, vous pouvez utiliser l'une qui conviennent à vos besoins (je vous recommande d'utiliser Euclidienne de fonction)
Tronquant la partie décimale de la fonction
Partie entière de la fonction
Euclidienne fonction
%
peut retourner des résultats négatifs (ce qui est le but de ces fonctions, régler le problème)parseInt(-41).mod(-7)
serait de retour-6
au lieu de1
(et c'est exactement le but de la partie entière de la fonction que j'ai écrit)Il y a un MNP paquet qui va faire le travail pour vous. Vous pouvez l'installer avec la commande suivante.
npm install just-modulo --save
Utilisation copié à partir du fichier README
GitHub peut être trouvé via le lien suivant:
https://github.com/angus-c/just/tree/master/packages/number-modulo