Division entière avec rest en JavaScript?

En JavaScript, comment puis-je obtenir:

  1. le nombre entier de fois qu’un entier donné va dans un autre?
  2. le rest?

Pour un certain nombre y et un diviseur x calculer le quotient ( quotient ) et le rest ( remainder ) comme:

 var quotient = Math.floor(y/x); var remainder = y % x; 

Je ne suis pas un expert des opérateurs binarys, mais voici un autre moyen d’obtenir le nombre entier:

 var num = ~~(a / b); 

Cela fonctionnera correctement pour les nombres négatifs, tandis que Math.floor() tournera dans la mauvaise direction.

Cela semble également correct:

 var num = (a / b) >> 0; 

J’ai fait des tests de vitesse sur Firefox.

 -100/3 // -33.33..., 0.3663 millisec Math.floor(-100/3) // -34, 0.5016 millisec ~~(-100/3) // -33, 0.3619 millisec (-100/3>>0) // -33, 0.3632 millisec (-100/3|0) // -33, 0.3856 millisec (-100-(-100%3))/3 // -33, 0.3591 millisec /* a=-100, b=3 */ a/b // -33.33..., 0.4863 millisec Math.floor(a/b) // -34, 0.6019 millisec ~~(a/b) // -33, 0.5148 millisec (a/b>>0) // -33, 0.5048 millisec (a/b|0) // -33, 0.5078 millisec (a-(a%b))/b // -33, 0.6649 millisec 

Ce qui précède est basé sur 10 millions d’essais pour chacun.

Conclusion: Utilisez (a/b>>0) (ou (~~(a/b)) ou (a/b|0) ) pour obtenir environ 20% de gain en efficacité. Gardez également à l’esprit qu’elles ne sont pas cohérentes avec Math.floor , quand a/b<0 && a%b!=0 .

ES6 introduit la nouvelle méthode Math.trunc . Cela permet de corriger la réponse de @ MarkElliot pour la faire fonctionner avec des nombres négatifs aussi:

 var div = Math.trunc(y/x); var rem = y % x; 

Notez que les méthodes Math ont l’avantage par rapport aux opérateurs binarys de travailler avec des nombres supérieurs à 2 31 .

 var remainder = x % y; return (x - remainder) / y; 

Vous pouvez utiliser la fonction parseInt pour obtenir un résultat tronqué.

 parseInt(a/b) 

Pour obtenir un rest, utilisez l’opérateur mod:

 a%b 

parseInt a des pièges avec les chaînes, pour éviter d’utiliser le paramètre radix avec la base 10

 parseInt("09", 10) 

Dans certains cas, la représentation sous forme de chaîne du nombre peut être une notation scientifique, dans ce cas, parseInt produira un résultat erroné.

 parseInt(100000000000000000000000000000000, 10) // 1e+32 

Cet appel produira 1 comme résultat.

JavaScript calcule à droite le plancher des nombres négatifs et le rest des nombres non entiers, en suivant les définitions mathématiques correspondantes.

FLOOR est défini comme “le plus grand nombre entier plus petit que le paramètre”, donc:

  • nombres positifs: FLOOR (X) = partie entière de X;
  • nombres négatifs: FLOOR (X) = partie entière de X moins 1 (car il doit être plus petit que le paramètre, c’est-à-dire plus négatif!)

REMAINDER est défini comme le “rest” d’une division (arithmétique euclidienne). Lorsque le dividende n’est pas un nombre entier, le quotient n’est généralement pas un entier, c’est-à-dire qu’il n’ya pas de rest, mais si le quotient est forcé à être un entier (et c’est ce qui arrive nombre à virgule flottante), il y aura un non-entier “restant”, évidemment.

JavaScript calcule tout comme prévu, donc le programmeur doit faire attention à poser les bonnes questions (et les gens doivent faire attention à ce qui est demandé!) La première question de Yarin n’était PAS “quelle est la division entière de X par Y”, mais au lieu de cela, “le nombre entier de fois qu’un nombre entier donné passe à un autre”. Pour les nombres positifs, la réponse est la même pour les deux, mais pas pour les nombres négatifs, car la division entière (dividende par diviseur) sera inférieure de 1 au nombre de fois qu’un diviseur “entrera” dans un autre (dividende). En d’autres termes, FLOOR renverra la réponse correcte pour une division entière d’un nombre négatif, mais Yarin ne l’a pas demandé!

gammax a répondu correctement, ce code fonctionne comme demandé par Yarin. D’autre part, Samuel a tort, il n’a pas fait les calculs, je suppose, ou il aurait vu que ça marche (aussi, il n’a pas dit quel était le diviseur de son exemple, mais j’espère que c’était 3):

Reste = X% Y = -100% 3 = -1

GoesInto = (X – Reste) / Y = (-100 – -1) / 3 = -99 / 3 = -33

En passant, j’ai testé le code sur Firefox 27.0.1, il a fonctionné comme prévu, avec des nombres positifs et négatifs et aussi avec des valeurs non entières, à la fois pour le dividende et le diviseur. Exemple:

-100,34 / 3,57: GoesInto = -28, rest = -0,3800000000000079

Oui, j’ai remarqué, il y a un problème de précision, mais je n’ai pas eu le temps de le vérifier (je ne sais pas si c’est un problème avec Firefox, Windows 7 ou avec le FPU de mon processeur). Pour la question de Yarin, qui ne concerne que des entiers, le code de la gammax fonctionne parfaitement.

Math.floor(operation) renvoie la valeur arrondie de l’opération.

Exemple de 1ère question:

 var x = 5; var y = 10.4; var z = Math.floor(x + y); console.log(z); 

Console:

15

Exemple de 2 ème question:

 var x = 14; var y = 5; var z = Math.floor(x%y); console.log(x); 

Console:

4

Le commentaire d’ Alex Moore-Niemi en réponse:

Pour les Rubyists ici de Google à la recherche de divmod , vous pouvez l’implémenter en tant que tel:

 function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; } 

Résultat:

 // [2, 33] 

Si vous divisez simplement par des puissances de deux, vous pouvez utiliser des opérateurs binarys:

 export function divideBy2(num) { return [num >> 1, num & 1]; } export function divideBy4(num) { return [num >> 2, num & 3]; } export function divideBy8(num) { return [num >> 3, num & 7]; } 

(Le premier est le quotient, le second le rest)

Le calcul du nombre de pages peut se faire en une seule étape: Math.ceil (x / y)

Vous pouvez utiliser ternary pour décider également comment gérer les valeurs entières positives et négatives.

 var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1 

Si le nombre est positif, tout va bien. Si le nombre est négatif, il appenda 1 en raison de la façon dont Math.floor traite les négatifs.

J’utilise normalement (a - a % b) / b . Ce n’est probablement pas le plus élégant, mais ça marche.

Cela va toujours tronquer vers zéro. Je ne sais pas s’il est trop tard, mais le voici:

 function intdiv(dividend, divisor) { divisor = divisor - divisor % 1; if (divisor == 0) throw new Error("division by zero"); dividend = dividend - dividend % 1; var rem = dividend % divisor; return { remainder: rem, quotient: (dividend - rem) / divisor }; }