web-dev-qa-db-fra.com

Division entière avec reste en JavaScript?

En JavaScript, comment puis-je obtenir:

  1. le nombre entier de fois qu'un entier donné passe dans un autre?
  2. le reste?
762
Yarin

Pour un nombre y et un diviseur x, calculer le quotient (quotient) et le reste (remainder) comme

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

Je ne suis pas un expert en opérateurs de bits, mais voici une autre façon d'obtenir le nombre entier:

var num = ~~(a / b);

Cela fonctionnera également correctement pour les nombres négatifs, alors que Math.floor() se retournera dans la mauvaise direction.

Cela semble correct aussi:

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

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 un gain d'efficacité d'environ 20%. Gardez également à l'esprit qu'ils sont tous incompatibles avec Math.floor, lorsque a/b<0 && a%b!=0.

170
KalEl

ES6 introduit la nouvelle méthode Math.trunc . Cela permet de corriger @ La réponse de MarkElliot pour que cela fonctionne aussi pour les nombres négatifs:

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

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

105
Oriol
var remainder = x % y;
return (x - remainder) / y;
21
gammax

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

parseInt(a/b)

Pour obtenir un reste, utilisez l'opérateur mod:

a%b

parseInt a quelques 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.

11

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

FLOOR est défini comme "le plus grand nombre entier inférieur au paramètre", ainsi:

  • 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!)

RESTANT est défini comme le "reste" d'une division (arithmétique euclidienne). Lorsque le dividende n’est pas un entier, le quotient n’est généralement pas non plus un entier, c’est-à-dire qu’il n’ya pas de reste, mais si le quotient est forcé d’être un entier (et c’est ce qui se produit lorsque nombre à virgule flottante), il y aura évidemment un "reste" non-entier.

JavaScript calcule tout comme prévu. Le programmeur doit donc veiller à poser les bonnes questions (et les gens à bien répondre à 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 entier donné devient 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 -1 plus petite que le nombre de fois qu'un nombre (diviseur) "passe en" 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 le calcul, je suppose, sinon il aurait vu que cela fonctionnait (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

A propos, j'ai testé le code sur Firefox 27.0.1, il a fonctionné comme prévu, avec des nombres positifs et négatifs, ainsi que des valeurs non entières, tant pour le dividende que pour le diviseur. Exemple:

-100.34/3.57: GoesInto = -28, Reste = -0.3800000000000079

Oui, j'ai remarqué qu'il y avait un problème de précision, mais je n'ai pas eu le temps de le vérifier (je ne sais pas s'il s'agit d'un problème avec Firefox, Windows 7 ou avec le FPU de mon processeur). Pour la question de Yarin, cependant, qui ne concerne que des entiers, le code du gammax fonctionne parfaitement.

6
Cyberknight

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

Exemple de 1st question:

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

console.log(z);

Console:

15

Exemple de 2dakota du Nord question:

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

console.log(x);

Console:

4

5
Aetricity

Le commentaire de Alex Moore-Niemi :

Pour les rubyists de Google à la recherche de divmod, vous pouvez l’appliquer 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]
2
Alex

Si vous divisez simplement avec des puissances de deux, vous pouvez utiliser des opérateurs au niveau des bits:

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 reste)

1
Konstantin Möllers

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

1
user1920925

Vous pouvez utiliser ternary pour décider 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, cela ajoutera 1 en raison de la façon dont Math.floor traite les négatifs.

0
John Galt

Cela tronquera toujours vers zéro . Je ne sais pas s'il est trop tard, mais voici ce qui se passe:

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
    };
}
0
bzim

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

0
Wolf Elkan

Si vous devez calculer le reste pour de très grands entiers, ce que le moteur d’exécution JS ne peut pas représenter en tant que tel (tout entier supérieur à 2 ^ 32 est représenté par un flottant et perd donc de la précision), vous devez faire quelques astuces.

Ceci est particulièrement important pour vérifier de nombreux cas de chiffres de contrôle qui sont présents dans de nombreux cas de notre vie quotidienne (numéros de compte bancaire, cartes de crédit, ...)

Tout d’abord, vous avez besoin de votre numéro sous forme de chaîne (sinon vous avez déjà perdu la précision et le reste n’a pas de sens).

str = '123456789123456789123456789'

Vous devez maintenant diviser votre chaîne en parties plus petites, suffisamment petites pour que la concaténation du reste et un morceau de chaîne puissent contenir 9 chiffres.

digits = 9 - String(divisor).length

Préparer une expression régulière pour scinder la chaîne

splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')

Par exemple, si digits est 7, l'expression rationnelle est

/.{1,7}(?=(.{7})+$)/g

Il correspond à une sous-chaîne non vide de longueur maximale 7, suivie d'un nombre de caractères multiple de 7 ((?=...) étant un signe de anticipation positif). Le 'g' consiste à faire en sorte que l'expression s'exécute sur toute la chaîne sans s'arrêter à la première .

Convertissez maintenant chaque partie en entier et calculez les restes par reduce (en rajoutant le reste précédent - ou 0 - multiplié par la puissance correcte de 10):

reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor

Cela fonctionnera à cause de l'algorithme de reste "soustraction":

n mod d = (n - kd) mod d

ce qui permet de remplacer n'importe quelle "partie initiale" de la représentation décimale d'un nombre par son reste, sans affecter le reste final.

Le code final ressemblerait à ceci:

function remainder(num, div) {
  const digits = 9 - String(div).length;
  const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
  const mult = Math.pow(10, digits);
  const reducer = (rem, piece) => (rem * mult + piece) % div;

  return str.match(splitter).map(Number).reduce(reducer, 0);
}
0
rewritten