¿Cómo convierto un número flotante a un número entero en JavaScript?


1110

Me gustaría convertir un flotante a un número entero en JavaScript. En realidad, me gustaría saber cómo hacer AMBAS conversiones estándar: truncando y redondeando. Y de manera eficiente, no mediante la conversión a una cadena y el análisis.


83
Si no lo sabía, todos los números en JavaScript son flotantes. A partir de la especificación:
algunos

66
4.3.20 Tipo de número: El tipo de número es un conjunto de valores que representan números. En ECMAScript, el conjunto de valores representa los valores IEEE 754 de formato de doble precisión de 64 bits, incluidos los valores especiales de "No es un número" (NaN), infinito positivo e infinito negativo.
algunos

99
Sí, Javascript no tiene un tipo "entero" distinto, pero todavía no es raro que necesite hacer esta conversión. Por ejemplo, en mi aplicación, los usuarios escribieron un número (posiblemente incluyendo centavos). Tuve que truncar los centavos y mostrar w / comas. El paso 1 fue convertir a int.
mcherm

1
también útil: comparación de velocidad de todos los métodos jsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..

1
@karl: Si acepto la entrada en un campo, podría controlar qué caracteres acepto, pero podría estar haciendo todo tipo de procesamiento en Javascript, no solo aceptando la entrada del usuario. Incluso entonces, podría quererlo para cosas como la pasta de apoyo.
mcherm

Respuestas:


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

Referencia de objeto matemático


Ejemplos

Positivo
// 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
Negativo
// 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
Positivo: números más grandes
// 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
Negativo: números más grandes
// 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

82
Como se mencionó en otra respuesta, se puede hacer un truncamiento seguro negativo usando var intValue = ~~floatValue;. Si la notación es demasiado oscuro para sus gustos, simplemente esconderlo en una función: function toInt(value) { return ~~value; }. (Esto también convierte las cadenas en enteros, si lo desea).
Keen

44
Votaría si esta respuesta tuviera entrada / salida de ejemplo.
J. Random Coder

77
Con respecto al comentario ~~ limita el valor a enteros con signo de 32 bits, mientras que Math.floor / ceil / round puede manejar hasta 53 bits (Number.MAX_SAFE_INTEGER 9007199254740991). Esto se menciona en la respuesta a continuación, pero vale la pena repetirlo aquí para quienes lean estos comentarios.
John

2
Lea desde abajo en varios lugares: Math.trunc(val);Comente porque esta es la respuesta aceptada
Old Badman Gray

No funciona con precisión exacta para valores como2.3 - 2.3 % 1
Lapys

301

Operador OR a nivel de bit

Se puede usar un operador u bit a bit para truncar figuras de punto flotante y funciona tanto para positivos como para negativos:

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

Resultados

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

¿Comparación de rendimiento?

He creado una prueba JSPerf que compara el rendimiento entre:

  • Math.floor(val)
  • val | 0 bitwise O
  • ~~val NO bit a bit
  • parseInt(val)

eso solo funciona con números positivos. En este caso, es seguro usar operaciones bit a bit como Math.floorfunción.

Pero si necesita que su código funcione con positivos y negativos , entonces una operación bit a bit es la más rápida (O es la preferida). Esta otra prueba JSPerf compara lo mismo donde es bastante obvio que debido a la comprobación adicional de signos, Math es ahora el más lento de los cuatro.

Nota

Como se indicó en los comentarios, los operadores BITWISE operan con enteros de 32 bits con signo, por lo tanto, se convertirán grandes números, por ejemplo:

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987

@FabioPoloni: sí, muy simple y parece que los operadores bit a bit son los más rápidos. Especialmente, el operador OR es siempre el más rápido a menudo igualado por las operaciones NOT y Math, aunque las operaciones Math también son las más lentas cuando tiene que admitir números negativos, porque agrega una verificación adicional del signo de número.
Robert Koritnik

99
@thefourtheye: todas las operaciones bit a bit, excepto el desplazamiento a la derecha sin signo, funcionan en enteros de 32 bits con signo. Por lo tanto, el uso de operaciones bit a bit en valores de coma flotante los convertirá en un número entero que elimina los dígitos después del punto decimal.
Robert Koritnik

3
Si solo lo necesita para números positivos, Math.floor()es más rápido (al menos según mi ejecución de su primera prueba JSPerf en Google Chrome, versión 30.0.1599.101), más robusto (porque no depende de cómo se representan los números en bits, que puede cambiar y posiblemente romper esta solución bit a bit), y lo más importante, más explícito.
ma11hew28

8
Tenga en cuenta que los operadores bit a bit operan con números de 32 bits. No funcionarán para números demasiado grandes para 32 bits.
Kat

2
~~es mejor porque es un operador unario. 4.2|0+4igual 4pero ~~4.2+4igual8
Janus Troelsen

94

Nota: ¡No se puede usar Math.floor()como un reemplazo para truncar, porque Math.floor(-3.1) = -4y no -3!

Un reemplazo correcto para truncar sería:

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

    return Math.floor(value);
}

1
Eso depende del comportamiento deseado para los números negativos. Algunos usos necesitan números negativos para mapear al valor más negativo (-3.5 -> -4) y algunos requieren que se mapeen al entero más pequeño (-3.5 -> -3). El primero normalmente se llama "piso". La palabra "truncar" a menudo se usa para describir cualquier comportamiento. En mi caso, solo iba a alimentarlo con números negativos. Pero este comentario es una advertencia útil para aquellos que sí se preocupan por el comportamiento negativo de los números.
mcherm

28
@mcherm: Entonces no parecen entender el término "truncar" correctamente. Truncar hace exactamente como su nombre lo indica: trunca los dígitos. Nunca es (en el sentido general) equivalente a piso o techo. en.wikipedia.org/wiki/Truncation
Thanatos

55
Math.trunc(value)fue agregado en ECMAScript 6
4esn0k

2
floorredondea hacia -infinito, truncateredondea hacia cero. ( ceilredondea hacia + infinito).
Peter Cordes

46

Se puede usar un operador doble no bit a bit para truncar los flotadores. Las otras operaciones que usted ha mencionado están disponibles a través Math.floor, Math.ceily Math.round.

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

Más detalles cortesía de James Padolsey.


1
Probablemente sea algo malo para el código de producción (ya que es oscuro), pero era exactamente lo que necesitaba para codificar el golf de mi <canvas>motor de representación de fuentes en JS . ¡Gracias!
Kragen Javier Sitaker

10
Esto también se puede lograr con n | 0.
Jay Douglass

17
Tenga en cuenta que cualquiera de los métodos (~~ n o n | 0) solo funciona en números hasta 2 ^ 31-1, o 2147483647. 2147483648 o superior devolverá un resultado incorrecto; por ejemplo, 2147483647 | 0 devuelve -2147483648 y 4294967295 | 0 devuelve -1, que casi definitivamente no es lo que desea.
Ed Bayiates

40

Para truncar:

var intvalue = Math.floor(value);

Por ronda:

var intvalue = Math.round(value);

66
Math.floor no trunca los valores negativos. Ver respuesta arriba. De lo contrario, buena respuesta.
oligofren

Si está interesado en el rendimiento, he puesto un pequeño caso de prueba aquí: jsperf.com/dsafdgdfsaf/2 (var | 0 gana aquí).
Cybolic

25

Puede usar el método parseInt para no redondear. Tenga cuidado con la entrada del usuario debido a las opciones de prefijo 0x (hexadecimal) y 0 (octal).

var intValue = parseInt(floatValue, 10);

1
Esto es realmente útil cuando solo quieres la parte entera de un decimal, sin redondear hacia arriba o hacia abajo, que es lo que hacen .round, .ceil y .floor.
Judá Gabriel Himango

1
... incluso cuando simplemente se trunca, este parece ser el método más lento. jsperf.com/float-to-int-conversion-comparison
Robert Koritnik

2
Siempre pase el segundo valor a parseInt para especificar qué base espera. Entonces, parseInt (floatValue, 10) para obtener siempre la base 10.
Tim Tisdall

3
Aunque esto es viejo, esta pregunta parece ser una que se hace con bastante frecuencia, por lo que lo pondré aquí como advertencia. Si el valor se representaría usando la notación "e" debido a su tamaño, solo dará como resultado un dígito, no lo que se espera. Por ejemplo, parseInt(1000000000000000000000, 10);da como resultado 1, no 1 000 000 000 000 000 000 000. De todos modos, la pregunta explícitamente no quería " convertir a una cadena y analizar ", aunque eso es relativamente menor ...;)
Qantas 94 Heavy

44
@ Qantas94Heavy La razón de este comportamiento es porque parseInt()espera que una cadena no sea un número como primer parámetro. Cuando pasa este número entero, se convierte 1e21y luego parseIntanaliza la cadena 1e21, lo que da como resultado 1.
Olaf Dietsche

18

Desplazamiento de bits por 0, que es equivalente a la división por 1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2

44
Pequeña nota: >> 0parece funcionar solo para enteros < 2 ^ 31-1 , y >>> 0para enteros < 2 ^ 32-1 . Esto devuelve 0 para valores mayores
Romuald Brunet

@RomualdBrunet, sí, JavaScript define claramente todas las operaciones bit a bit como operando en números de 32 bits. Eso está en las especificaciones.
Alexis Wilke

Esto funciona como Javascript realiza operaciones bit a bit solo con enteros de 32 bits (con signo) como se indica en una respuesta anterior. Por lo tanto, cualquier operación de bits que parece no hacer nada (como un cambio para 0, O con 0, Y con 1, doble NO) todavía necesita un intérprete de Javascript para convertir el valor a 32 bits int.
FrankKrumnow


7

Hay muchas sugerencias aquí. El OR bit a bit parece ser el más simple con diferencia. Aquí hay otra solución corta que también funciona con números negativos utilizando el operador de módulo. Probablemente sea más fácil de entender que el bit a bit O:

intval = floatval - floatval%1;

Este método también funciona con números de alto valor donde ni '| 0' ni '~~' ni '>> 0' funcionan correctamente:

> n=4294967295;
> n|0
-1
> ~~n
-1
> n>>0
-1
> n-n%1
4294967295

Si se refiere a otra respuesta, agréguele una referencia o esboce brevemente su idea.
bertl

5

Para truncar :

// 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

Para redondear :

Math.round( 1.5 );  // 2
Math.round( 1.49 ); // 1
Math.round( -1.6 ); // -2
Math.round( -1.3 ); // -1

5

Una forma más posible: utilice la operación 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 prioridad de las operaciones bit a bit es menor que la prioridad de las operaciones matemáticas, es útil. Pruebe en https://jsfiddle.net/au51uj3r/


2

Si busca un Mathobjeto nativo en JavaScript, obtiene todas las funciones para trabajar en números y valores, etc.

Básicamente, lo que quieres hacer es bastante simple y nativo en JavaScript ...

Imagina que tienes el siguiente número:

const myValue = 56.4534931;

y ahora si quieres redondearlo al número más cercano, simplemente haz lo siguiente:

const rounded = Math.floor(myValue);

y obtienes:

56

Si desea redondearlo al número más cercano, simplemente haga lo siguiente:

const roundedUp = Math.ceil(myValue);

y obtienes:

57

Además, Math.roundsimplemente redondearlo a un número mayor o menor depende de cuál esté más cerca del número de flotador.

También puede usar ~~detrás del número flotante, que convertirá un flotante en un número entero.

Puedes usarlo como ~~myValue...


Tenga cuidado con el ~~porque si el número es mayor que el límite int 32, cambiará el valor al valor límite 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


0

Solo quiero señalar que monetariamente quieres redondear, y no truncar. Estar fuera por un centavo es mucho menos probable, ya que 4.999452 * 100 redondeado le dará 5, una respuesta más representativa.

Y además de eso, no se olvide del redondeo bancario , que es una forma de contrarrestar el sesgo ligeramente positivo que produce el redondeo directo: su aplicación financiera puede requerirlo.

Redondeo gaussiano / bancario en JavaScript


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.