Comment convertir un nombre flottant en nombre entier en JavaScript?

1110

Je voudrais convertir un flotteur en nombre entier en JavaScript. En fait, j'aimerais savoir comment faire les DEUX conversions standard: en tronquant et en arrondissant. Et efficacement, pas via la conversion en chaîne et l'analyse.

mcherm
la source
83
Si vous ne le saviez pas, tous les nombres en javascript sont des flottants. D'après les spécifications:
certains
6
4.3.20 Type de numéro: Le type de numéro est un ensemble de valeurs représentant des nombres. Dans ECMAScript, l'ensemble de valeurs représente les valeurs IEEE 754 au format 64 bits à double précision, y compris les valeurs spéciales «Not-a-Number» (NaN), l'infini positif et l'infini négatif.
certains
9
Oui, Javascript n'a pas de type "entier" distinct, mais il n'est pas rare de devoir effectuer cette conversion. Par exemple, dans mon application, les utilisateurs ont tapé un nombre (y compris éventuellement des cents). J'ai dû tronquer les cents et afficher des virgules. L'étape 1 consistait à convertir en int.
mcherm
1
également utile: comparaison de vitesse de toutes les méthodes jsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..
1
@karl: Si j'accepte la saisie dans un champ, je pourrai peut-être contrôler les caractères que j'accepte, mais je pourrais faire toutes sortes de traitements en Javascript, pas seulement accepter la saisie utilisateur. Même alors, je pourrais le vouloir pour des choses comme la pâte de support.
mcherm

Réponses:

1609
var intvalue = Math.floor( floatvalue );
var intvalue = Math.ceil( floatvalue ); 
var intvalue = Math.round( floatvalue );

// `Math.trunc` was added in ECMAScript 6
var intvalue = Math.trunc( floatvalue );

Référence d'objet mathématique


Exemples

Positif
// value=x        //  x=5          5<x<5.5      5.5<=x<6  

Math.floor(value) //  5            5            5
Math.ceil(value)  //  5            6            6
Math.round(value) //  5            5            6
Math.trunc(value) //  5            5            5
parseInt(value)   //  5            5            5
~~value           //  5            5            5
value | 0         //  5            5            5
value >> 0        //  5            5            5
value >>> 0       //  5            5            5
value - value % 1 //  5            5            5
Négatif
// value=x        // x=-5         -5>x>=-5.5   -5.5>x>-6

Math.floor(value) // -5           -6           -6
Math.ceil(value)  // -5           -5           -5
Math.round(value) // -5           -5           -6
Math.trunc(value) // -5           -5           -5
parseInt(value)   // -5           -5           -5
value | 0         // -5           -5           -5
~~value           // -5           -5           -5
value >> 0        // -5           -5           -5
value >>> 0       // 4294967291   4294967291   4294967291
value - value % 1 // -5           -5           -5
Positif - Plus grand nombre
// x = Number.MAX_SAFE_INTEGER/10 // =900719925474099.1

// value=x            x=900719925474099    x=900719925474099.4  x=900719925474099.5

Math.floor(value) //  900719925474099      900719925474099      900719925474099
Math.ceil(value)  //  900719925474099      900719925474100      900719925474100
Math.round(value) //  900719925474099      900719925474099      900719925474100
Math.trunc(value) //  900719925474099      900719925474099      900719925474099
parseInt(value)   //  900719925474099      900719925474099      900719925474099
value | 0         //  858993459            858993459            858993459
~~value           //  858993459            858993459            858993459
value >> 0        //  858993459            858993459            858993459
value >>> 0       //  858993459            858993459            858993459
value - value % 1 //  900719925474099      900719925474099      900719925474099
Négatif - Plus grand nombre
// x = Number.MAX_SAFE_INTEGER/10 * -1 // -900719925474099.1

// value = x      // x=-900719925474099   x=-900719925474099.5 x=-900719925474099.6

Math.floor(value) // -900719925474099     -900719925474100     -900719925474100
Math.ceil(value)  // -900719925474099     -900719925474099     -900719925474099
Math.round(value) // -900719925474099     -900719925474099     -900719925474100
Math.trunc(value) // -900719925474099     -900719925474099     -900719925474099
parseInt(value)   // -900719925474099     -900719925474099     -900719925474099
value | 0         // -858993459           -858993459           -858993459
~~value           // -858993459           -858993459           -858993459
value >> 0        // -858993459           -858993459           -858993459
value >>> 0       //  3435973837           3435973837           3435973837
value - value % 1 // -900719925474099     -900719925474099     -900719925474099
l'ombre de la lune
la source
82
Comme mentionné dans une autre réponse, une troncature sans danger peut être effectuée en utilisant var intValue = ~~floatValue; . Si la notation est trop obscure pour vos goûts, juste le cacher dans une fonction: function toInt(value) { return ~~value; }. (Cela convertit également les chaînes en entiers, si vous le souhaitez.)
Keen
4
Souhaiterait voter si cette réponse avait un exemple d'entrée / sortie.
J. Random Coder
7
Concernant le commentaire, ~~ limite la valeur à des entiers signés 32 bits, tandis que Math.floor / ceil / round peut gérer jusqu'à 53 bits (Number.MAX_SAFE_INTEGER 9007199254740991). Ceci est mentionné dans la réponse ci-dessous, mais il convient de le répéter ici pour ceux qui lisent ces commentaires.
John
2
Lire ci-dessous à plusieurs endroits: Math.trunc(val);commenter car c'est la réponse acceptée
Old Badman Gray
Ne fonctionne pas avec une précision exacte pour des valeurs comme2.3 - 2.3 % 1
Lapys
301

Opérateur OR au niveau du bit

Un opérateur au niveau du bit ou peut être utilisé pour tronquer les chiffres à virgule flottante et cela fonctionne pour les positifs comme pour les négatifs:

function float2int (value) {
    return value | 0;
}

Résultats

float2int(3.1) == 3
float2int(-3.1) == -3
float2int(3.9) == 3
float2int(-3.9) == -3

Comparaison des performances?

J'ai créé un test JSPerf qui compare les performances entre:

  • Math.floor(val)
  • val | 0 au niveau du bit OU au niveau du
  • ~~val au niveau du bit pas au niveau du
  • parseInt(val)

cela ne fonctionne qu'avec des nombres positifs. Dans ce cas, vous pouvez utiliser les opérations au niveau du bit et la Math.floorfonction en toute sécurité .

Mais si vous avez besoin de votre code pour travailler avec les positifs comme les négatifs , alors une opération au niveau du bit est la plus rapide (OU étant la préférée). Cet autre test JSPerf compare le même où il est assez évident qu'en raison du contrôle de signe supplémentaire, Math est maintenant le plus lent des quatre.

Remarque

Comme indiqué dans les commentaires, les opérateurs BITWISE fonctionnent sur des entiers 32 bits signés, donc les grands nombres seront convertis, par exemple:

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987
Robert Koritnik
la source
@FabioPoloni: oui super simple et il semble que les opérateurs au niveau du bit soient les plus rapides. En particulier, l'opérateur OR est toujours le plus rapide souvent associé aux opérations NOT et Math, bien que les opérations Math soient les plus lentes lorsque vous devez également prendre en charge les nombres négatifs, car cela ajoute une vérification supplémentaire du signe du nombre.
Robert Koritnik
9
@thefourtheye: Toutes les opérations au niveau du bit, à l'exception du décalage vers la droite non signé, fonctionnent sur des entiers 32 bits signés. Par conséquent, l'utilisation d'opérations au niveau du bit sur des valeurs à virgule flottante les convertira en un entier dépouillant les chiffres après le point décimal.
Robert Koritnik
3
Si vous en avez juste besoin pour les nombres positifs, Math.floor()est plus rapide (au moins selon mon exécution de votre premier test JSPerf sur Google Chrome, version 30.0.1599.101), plus robuste (car cela ne dépend pas de la façon dont les nombres sont représentés en bits, qui peut changer et éventuellement casser cette solution au niveau du bit), et surtout, plus explicite.
ma11hew28
8
Notez que les opérateurs au niveau du bit fonctionnent sur des nombres de 32 bits. Ils ne fonctionneront pas pour des nombres trop grands pour tenir en 32 bits.
Kat
2
~~c'est mieux car c'est un opérateur unaire. 4.2|0+4égal 4mais ~~4.2+4égal8
Janus Troelsen
94

Remarque: Vous ne pouvez pas utiliser Math.floor()comme remplacement de tronquer, car Math.floor(-3.1) = -4et non-3 !!

Un remplacement correct pour tronquer serait:

function truncate(value)
{
    if (value < 0) {
        return Math.ceil(value);
    }

    return Math.floor(value);
}
Jackson
la source
1
Cela dépend du comportement souhaité pour les nombres négatifs. Certaines utilisations nécessitent des nombres négatifs pour correspondre à la valeur la plus négative (-3,5 -> -4) et d'autres les obligent à correspondre au plus petit entier (-3,5 -> -3). Le premier est normalement appelé "étage". Le mot "tronquer" est souvent utilisé pour décrire l'un ou l'autre comportement. Dans mon cas, j'allais seulement lui donner des nombres négatifs. Mais ce commentaire est un avertissement utile pour ceux qui se soucient du comportement des nombres négatifs.
mcherm
28
@mcherm: Alors ils ne semblent pas comprendre correctement le terme "tronquer". Tronquer fait exactement comme son nom l'indique: il tronque les chiffres. Il n'est jamais (au sens général) équivalent au sol ou au plafond. en.wikipedia.org/wiki/Truncation
Thanatos
5
Math.trunc(value)a été ajouté dans ECMAScript 6
4esn0k
2
floorarrondit vers -infini, truncatearrondit vers zéro. ( ceilarrondit vers + infini).
Peter Cordes
46

Un double opérateur pas au niveau du bit peut être utilisé pour tronquer les flottants. Les autres opérations que vous avez mentionnés sont disponibles à travers Math.floor, Math.ceilet Math.round.

> ~~2.5
2
> ~~(-1.4)
-1

Plus de détails gracieuseté de James Padolsey.

Brad
la source
1
C'est probablement une mauvaise chose à faire pour le code de production (car il est obscur) mais c'était exactement ce dont j'avais besoin pour jouer au code mon <canvas>moteur de rendu de polices dans JS . Je vous remercie!
Kragen Javier Sitaker
10
Cela peut également être accompli avec n | 0.
Jay Douglass
17
Notez que l'une ou l'autre méthode (~~ n ou n | 0) ne fonctionne que sur les nombres jusqu'à 2 ^ 31-1 ou 2147483647. 2147483648 ou supérieur renverra un résultat incorrect; par exemple, 2147483647 | 0 renvoie -2147483648 et 4294967295 | 0 renvoie -1, ce qui n'est certainement pas ce que vous voulez.
Ed Bayiates du
40

Pour tronquer:

var intvalue = Math.floor(value);

Pour ronde:

var intvalue = Math.round(value);
Mike
la source
6
Math.floor ne tronque pas les valeurs négatives. Voir la réponse ci-dessus. Sinon, belle réponse.
oligofren
Si vous êtes intéressé par les performances, j'ai mis un petit cas de test ici: jsperf.com/dsafdgdfsaf/2 (var | 0 gagne ici).
Cybolic
25

Vous pouvez utiliser la méthode parseInt pour aucun arrondi. Soyez prudent avec l'entrée utilisateur en raison des options de préfixe 0x (hex) et 0 (octal).

var intValue = parseInt(floatValue, 10);
Graeme Wicksted
la source
1
Ceci est en fait utile lorsque vous voulez juste la partie entière d'une décimale, sans arrondir vers le haut ou vers le bas, ce que font tous les .round, .ceil et .floor.
Judah Gabriel Himango
1
... même en tronquant simplement cela semble être la méthode la plus lente. jsperf.com/float-to-int-conversion-comparison
Robert Koritnik
2
Passez toujours la 2e valeur à parseInt pour spécifier à quelle base vous vous attendez. Donc, parseInt (floatValue, 10) pour toujours obtenir la base 10.
Tim Tisdall
3
Bien que cela soit ancien, cette question semble être assez souvent posée, donc je vais mettre cela ici comme un avertissement. Si la valeur est représentée à l'aide de la notation "e" en raison de sa taille, elle ne produira qu'un seul chiffre, et non ce qui est attendu. Par exemple, cela parseInt(1000000000000000000000, 10);donne 1, pas 1 000 000 000 000 000 000 000 000. Quoi qu'il en soit, la question ne voulait pas explicitement " convertir en chaîne et analyser ", bien que ce soit relativement mineur ...;)
Qantas 94 Heavy
4
@ Qantas94Heavy La raison de ce comportement est dû au fait qu'elle parseInt()attend une chaîne et non un nombre comme premier paramètre. Lorsque vous passez cet entier, il est converti en 1e21puis parseIntanalyse la chaîne 1e21, ce qui se traduit par 1.
Olaf Dietsche
18

Décalage de bits de 0, ce qui équivaut à une division de 1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2
Prasanth
la source
4
Petite note: >> 0semble fonctionner uniquement pour les entiers < 2 ^ 31-1 , et >>> 0pour les entiers < 2 ^ 32-1 . Cela renvoie 0 pour des valeurs plus grandes
Romuald Brunet
@RomualdBrunet, oui, JavaScript définit clairement toutes les opérations au niveau du bit comme fonctionnant sur des nombres de 32 bits. C'est dans les spécifications.
Alexis Wilke
Cela fonctionne comme Javascript ne fait des opérations au niveau du bit qu'avec des entiers 32 bits (signés) comme indiqué dans une réponse ci-dessus. Donc, toute opération binaire qui semble ne rien faire (comme un décalage pour 0, OR avec 0, ET avec 1, double NOT) a toujours besoin d'un interpréteur Javascript pour convertir la valeur en 32 bits int.
FrankKrumnow
9

Dans votre cas, lorsque vous voulez une chaîne à la fin (afin d'insérer des virgules), vous pouvez également simplement utiliser la Number.toFixed()fonction, cependant, cela effectuera l'arrondi.

Russell Leggett
la source
7

Il y a de nombreuses suggestions ici. L'OR au niveau du bit semble de loin le plus simple. Voici une autre solution courte qui fonctionne également avec des nombres négatifs en utilisant l'opérateur modulo. Il est probablement plus facile à comprendre que le bit à bit OU:

intval = floatval - floatval%1;

Cette méthode fonctionne également avec des nombres de valeur élevée où ni '| 0' ni '~~' ni '>> 0' ne fonctionnent correctement:

> n=4294967295;
> n|0
-1
> ~~n
-1
> n>>0
-1
> n-n%1
4294967295
Juliane Holzt
la source
Si vous faites référence à une autre réponse, veuillez y ajouter une référence ou esquisser brièvement son idée.
bertl
5

Pour tronquer :

// Math.trunc() is part of the ES6 spec
Math.trunc( 1.5 );  // returns 1
Math.trunc( -1.5 ); // returns -1
// Math.floor( -1.5 ) would return -2, which is probably not what you wanted

Pour arrondir :

Math.round( 1.5 );  // 2
Math.round( 1.49 ); // 1
Math.round( -1.6 ); // -2
Math.round( -1.3 ); // -1
Rasoir
la source
5

Une autre façon possible - utilisez l'opération XOR:

console.log(12.3 ^ 0); // 12
console.log("12.3" ^ 0); // 12
console.log(1.2 + 1.3 ^ 0); // 2
console.log(1.2 + 1.3 * 2 ^ 0); // 3
console.log(-1.2 ^ 0); // -1
console.log(-1.2 + 1 ^ 0); // 0
console.log(-1.2 - 1.3 ^ 0); // -2

La priorité des opérations au niveau du bit est inférieure à la priorité des opérations mathématiques, c'est utile. Essayez sur https://jsfiddle.net/au51uj3r/

Dmitry Kharitonov
la source
2

Si regardez en natif Math objet en JavaScript, vous obtenez tout le tas de fonctions pour travailler sur les nombres et les valeurs, etc.

Fondamentalement, ce que vous voulez faire est assez simple et natif en JavaScript ...

Imaginez que vous avez le numéro ci-dessous:

const myValue = 56.4534931;

et maintenant si vous voulez l'arrondir au nombre le plus proche, faites simplement:

const rounded = Math.floor(myValue);

et vous obtenez:

56

Si vous voulez l'arrondir au nombre le plus proche, faites simplement:

const roundedUp = Math.ceil(myValue);

et vous obtenez:

57

De Math.roundmême, l'arrondir à un nombre supérieur ou inférieur dépend de celui qui est le plus proche du nombre de flots.

Vous pouvez également utiliser ~~derrière le nombre flottant, qui convertira un flotteur en nombre entier.

Vous pouvez l'utiliser comme ~~myValue...

Alireza
la source
Veuillez faire attention au ~~car, si le nombre est supérieur à la limite int 32, il changera la valeur en valeur limite int 32.
Machado
1

//Convert a float to integer

Math.floor(5.95)
//5

Math.ceil(5.95)
//6

Math.round(5.4)
//5

Math.round(5.5)
//6

Math.trunc(5.5)
//5

//Quick Ways
console.log(5.95| 0)
console.log(~~5.95) 
console.log(5.95 >> 0)
//5

pk_code
la source
0

Je veux juste souligner que monétairement, vous voulez arrondir, et non tronquer. Être hors d'un sou est beaucoup moins probable, car 4,999452 * 100 arrondi vous donnera 5, une réponse plus représentative.

Et en plus de cela, n'oubliez pas l'arrondi bancaire , qui est un moyen de contrer le biais légèrement positif que donne l'arrondi simple - votre application financière peut l'exiger.

Arrondi gaussien / banquier en JavaScript

Gerard ONeill
la source