Un de mes collègues est tombé sur une méthode pour plancher les nombres flottants en utilisant un bit ou:
var a = 13.6 | 0; //a == 13
Nous en parlions et nous nous posions quelques questions.
- Comment ça marche? Notre théorie était que l'utilisation d'un tel opérateur convertit le nombre en entier, supprimant ainsi la partie fractionnaire
- Y a-t-il des avantages à faire
Math.floor
? C'est peut-être un peu plus rapide? (jeu de mots non prévu) - Y a-t-il des inconvénients? Peut-être que cela ne fonctionne pas dans certains cas? La clarté est une évidence, car nous avons dû le comprendre, et bien, j'écris cette question.
Merci.
javascript
floating-point
bit-manipulation
Alex Turpin
la source
la source
3000000000.1 | 0
-1294967296. Donc, cette méthode ne peut pas être appliquée pour les calculs d'argent (en particulier dans les cas où vous multipliez par 100 pour éviter les nombres décimaux).0.1 + 0.2 == 0.3
dans une console JavaScript. Si votre langue le prend en charge, vous devez utiliser un type décimal. Sinon, stockez les cents à la place.Réponses:
Toutes les opérations au niveau du bit, à l'exception du décalage à droite non signé
>>>
, fonctionnent sur des entiers 32 bits signés. Ainsi, l'utilisation d'opérations au niveau du bit convertira un flottant en entier.http://jsperf.com/or-vs-floor/2 semble légèrement plus rapide
Math.floor(NaN) === NaN
tandis que(NaN | 0) === 0
la source
Math.floor(NaN) === NaN
, tandis que(NaN | 0) === 0
. Cette différence peut être importante dans certaines applications.asm.js
(où je l'ai appris pour la première fois). C'est plus rapide si pour aucune autre raison car il n'appelle pas une fonction sur l'Math
objet, une fonction qui pourrait à tout moment être remplacée comme dansMath.floor = function(...)
.(value | 0) === value
pourrait être utilisé pour vérifier qu'une valeur est en fait un entier et seulement un entier (comme dans le code source Elm @ dwayne-crooks linked). Etfoo = foo | 0
pourrait être utilisé pour contraindre n'importe quelle valeur à un entier (où les nombres de 32 bits sont tronqués et tous les non-nombres deviennent 0).Il s'agit de la troncature par opposition au revêtement de sol. La réponse de Howard est en quelque sorte correcte; Mais j'ajouterais que
Math.floor
fait exactement ce qu'il est censé faire en ce qui concerne les nombres négatifs. Mathématiquement, c'est ce qu'est un plancher.Dans le cas que vous avez décrit ci-dessus, le programmeur était plus intéressé par la troncature ou la suppression complète de la décimale. Cependant, la syntaxe qu'ils ont utilisée masque en quelque sorte le fait qu'ils convertissent le flottant en un int.
la source
Math.floor(8589934591.1)
produit le résultat attendu,8589934591.1 | 0
NE FAIT PAS .Dans ECMAScript 6, l'équivalent de
|0
est Math.trunc , un peu je devrais dire:la source
Math.trunc()
travailler avec un nombre supérieur ou égal à 2 ^ 31 et| 0
ne le fait pasVotre premier point est correct. Le nombre est converti en un entier et ainsi tous les chiffres décimaux sont supprimés. Veuillez noter que cela
Math.floor
arrondit à l'entier suivant vers moins l'infini et donne donc un résultat différent lorsqu'il est appliqué à des nombres négatifs.la source
Javascript représente
Number
sous forme de nombres flottants 64 bits Double Precision .Math.floor
fonctionne dans cet esprit.Les opérations au niveau du bit fonctionnent en 32 bits signé entiers . Les entiers signés 32 bits utilisent le premier bit comme signifiant négatif et les 31 autres bits sont le nombre. Pour cette raison, le nombre minimal et maximal autorisé des nombres signés 32 bits sont respectivement -2 147 483 648 et 2147483647 (0x7FFFFFFFF).
Donc, lorsque vous faites
| 0
, vous faites essentiellement& 0xFFFFFFFF
. Cela signifie que tout nombre représenté par 0x80000000 (2147483648) ou supérieur sera renvoyé sous la forme d'un nombre négatif.Par exemple:
Aussi. Les opérations au niveau du bit ne "plancher" pas. Ils tronquent , ce qui revient à dire qu'ils arrondissent le plus près
0
. Une fois que vous êtes passé aux nombres négatifs,Math.floor
arrondit vers le bas tandis que le bit commence à arrondir vers le haut .Comme je l'ai déjà dit, il
Math.floor
est plus sûr car il fonctionne avec des nombres flottants 64 bits. Le bit est plus rapide , oui, mais limité à une portée signée 32 bits.Résumer:
0 to 2147483647
.-2147483647 to 0
.-2147483648
et supérieurs à2147483647
.Si vous voulez vraiment améliorer les performances et utiliser les deux:
Juste pour ajouter des
Math.trunc
travaux comme des opérations au niveau du bit. Vous pouvez donc faire ceci:la source
Les spécifications indiquent qu'il est converti en entier:
Performance: cela a déjà été testé chez jsperf .
Remarque: lien mort vers la spécification supprimé
la source