Réponses:
Pour un certain nombre y
et un certain diviseur, x
calculez le quotient ( quotient
) et le reste ( remainder
) comme:
var quotient = Math.floor(y/x);
var remainder = y % x;
floor
et %
ensemble n'est pas cohérent de cette façon. Soit utiliser à la trunc
place de floor
(permettant ainsi des restes négatifs) ou utiliser la soustraction pour obtenir le reste ( rem = y - div * x
).
rem
toute façon, vous pouvez obtenir le quotient div
plus rapidement , sans revêtement de sol: (y - rem) / x
. 2. Au fait, l'opération modulo par la définition recommandée de Donald Knuth (signe-correspond-diviseur, pas le reste c'est-à-dire module euclidien, ni le signe-correspond-dividende JavaScript) est ce que nous pouvons coder en JavaScript comme function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.
Je ne suis pas un expert des opérateurs au niveau du bit, mais voici une autre façon d'obtenir le nombre entier:
var num = ~~(a / b);
Cela fonctionnera également correctement pour les nombres négatifs, tandis que Math.floor()
en arrondissant dans la mauvaise direction.
Cela semble également correct:
var num = (a / b) >> 0;
a/b | 0
~~int
, int | 0
et int >> 0
ne modifie pas l'argument initial, mais oblige l'interpréteur à passer la partie intégrante à l'opérateur.
floor
à peine dans la mauvaise direction, étant donné son nom - mais pas dans la direction que les gens veulent généralement!
a = 12447132275286670000; b = 128
Math.floor(a/b)
-> 97243220900677100
et ~~(a/b)
-> -1231452688
.
~~(5/2) --> 2
comme le fait (5/2)>>0 --> 2
, mais ~~(5/2) + 1 --> 3
, tout ~~(5/2)>>0 + 1 --> 1
. ~~
est un bon choix car la priorité est plus appropriée.
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
, quand a/b<0 && a%b!=0
.
Math.floor
les autres fonctions de l'API et qui sait qui, ou en savoir plus sur l' ~
opérateur (bit à bit) et sur le fonctionnement des opérations bit à bit dans JS, puis comprendre l'effet du double tilde?
Math.floor
mieux. Et même si ce n'est pas le cas, celui-ci est googleable.
ES6 introduit la nouvelle Math.trunc
méthode. Cela permet de corriger la réponse de @ MarkElliot pour qu'elle fonctionne également pour les nombres négatifs:
var div = Math.trunc(y/x);
var rem = y % x;
Notez que les Math
méthodes ont l'avantage sur les opérateurs au niveau du bit qu'elles fonctionnent avec des nombres supérieurs à 2 31 .
18014398509481984 == 18014398509481985
,.
~~(x/y)
. Besoin de prendre en charge de plus grands nombres jusqu'à 54 bits signés? Utilisez-le Math.trunc
si vous l'avez, ou Math.floor
autrement (corrigez les nombres négatifs). Besoin de prendre en charge des nombres encore plus importants? Utilisez une grande bibliothèque de nombres.
divmod
, vous pouvez l'implémenter comme tel:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
var remainder = x % y;
return (x - remainder) / y;
Math.trunc
:). J'ai vérifié avec 100,3; -100,3; 100, -3 et -100, -3. Bien sûr, beaucoup de temps s'est écoulé depuis votre commentaire et les choses changent.
J'utilise normalement:
const quotient = (a - a % b) / b;
const remainder = a % b;
Ce n'est probablement pas le plus élégant, mais ça marche.
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 incorrect.
parseInt(100000000000000000000000000000000, 10) // 1e+32
Cet appel produira 1 comme résultat.
parseInt
doit être évité autant que possible. Voici l'avertissement de Douglas Crockford: "Si le premier caractère de la chaîne est 0, alors la chaîne est évaluée en base 8 au lieu de base 10. En base 8, 8 et 9 ne sont pas des chiffres, donc parseInt (" 08 ") et parseInt ("09") produit 0 comme résultat. Cette erreur provoque des problèmes dans les programmes qui analysent les dates et les heures. Heureusement, parseInt peut prendre un paramètre radix, de sorte que parseInt ("08", 10) produit 8. Je vous recommande de toujours fournir le paramètre radix. " archive.oreilly.com/pub/a/javascript/excerpts/…
parseInt
faut éviter; juste qu'il y a quelques pièges à connaître. Vous devez être conscient de ces choses et être prêt à y faire face.
parseInt
avec un argument numérique. parseInt
est censé analyser des chaînes partiellement numériques, pas tronquer des nombres.
JavaScript calcule à droite le plancher des nombres négatifs et le reste des nombres non entiers, en suivant les définitions mathématiques pour eux.
FLOOR est défini comme "le plus grand nombre entier inférieur au paramètre", ainsi:
REMAINDER 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'y a pas de reste, mais si le quotient est forcé d'être un entier (et c'est ce qui se passe lorsque quelqu'un essaie d'obtenir le reste ou le module d'un nombre à virgule flottante), il restera évidemment un "non entier".
JavaScript calcule tout comme prévu, donc le programmeur doit faire attention à poser les bonnes questions (et les gens devraient faire attention à 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é va dans 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 inférieure à la fois où un nombre (diviseur) "entre" dans un autre (dividende). En d'autres termes, FLOOR retournera la bonne réponse 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'un autre côté, Samuel a tort, il n'a pas fait le calcul, 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 le cas) 3):
Reste = X% Y = -100% 3 = -1
GoesInto = (X - Reste) / Y = (-100 - -1) / 3 = -99 / 3 = -33
Soit dit 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 également avec des valeurs non entières, à la fois pour le dividende et le diviseur. Exemple:
-100,34 / 3,57: GoesInto = -28, reste = -0,3800000000000079
Oui, j'ai remarqué qu'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 le FPU de mon CPU). Pour la question de Yarin, qui n'implique que des entiers, le code du gammax fonctionne parfaitement.
Le calcul du nombre de pages peut être effectué en une seule étape: Math.ceil (x / y)
Alex Moore-NiemiCommentaire d' en réponse:
Pour les Rubyists ici de Google à la recherche de divmod
, vous pouvez l'implémenter comme tel:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Résultat:
// [2, 33]
divmod
utilisations division parqueté ( Math.floor
), qui diffère de la division tronquée ( Math.trunc
) lorsque sont impliqués des nombres négatifs. C'est le cas du package NPMdivmod
, Rubydivmod
, SWI-Prologdivmod
et probablement de nombreuses autres implémentations.
divmod
existe car il est exécuté deux fois plus vite que le calcul séparé des deux opérations. Fournir une telle fonction sans cet avantage de performance peut être déroutant.
Si vous divisez simplement avec des puissances de deux, vous pouvez utiliser des opérateurs au niveau du bit:
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)
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
.
Vous pouvez également utiliser ternaire 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, il ajoutera 1 en raison de la façon dont Math.floor gère les négatifs.
Cela sera toujours tronqué vers zéro. Je ne sais pas s'il est trop tard, mais voilà:
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
};
}
Si vous devez calculer le reste pour les très grands entiers, que le runtime JS ne peut pas représenter en tant que tels (tout entier supérieur à 2 ^ 32 est représenté comme un flottant et perd ainsi sa précision), vous devez faire un tour.
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 de tout reste et un morceau de chaîne puisse tenir en 9 chiffres.
digits = 9 - String(divisor).length
Préparez une expression régulière pour diviser 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, qui est suivie ( (?=...)
est une anticipation positive) par un nombre de caractères qui est multiple de 7. Le `` g '' consiste à faire en sorte que l'expression passe à travers toute la chaîne, sans s'arrêter à la première correspondance.
Maintenant, convertissez chaque partie en entier et calculez les restes par reduce
(en ajoutant 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 en raison de l'algorithme de reste "soustraction":
n mod d = (n - kd) mod d
ce qui permet de remplacer toute «partie initiale» de la représentation décimale d'un nombre par son reste, sans affecter le reste final.
Le code final ressemblerait à:
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);
}
3.5 % 2
évalue à 1,5. Assurez-vous de gérer (parseInt, sol, etc.) comme requis