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

1283

Me gustaría convertir un flotante en 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.

6
  • 92
    Si no lo sabía, todos los números en javascript son flotantes. De la especificación:some 28 de febrero de 2009 a las 2:40
  • 6
    4.3.20 Tipo de número: El tipo 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 64 bits de doble precisión, incluidos los valores especiales “No es un número” (NaN), infinito positivo e infinito negativo. some 28 de febrero de 2009 a las 2:41
  • 10
    Sí, Javascript no tiene un tipo "entero" distinto, pero aún así no es raro tener que 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 con comas. El paso 1 fue convertir a int. mcherm 28 feb 09 a las 15:40
  • 1
    también útil: comparación de velocidad de todos los métodos jsperf.com/math-floor-vs-math-round-vs-parseint/33c.. 26/07/12 a las 18:10
  • 1
    @karl: Si acepto la entrada en un campo, es posible que pueda 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 pasta de soporte. mcherm 30/10/12 a las 16:55
1881
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 de

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
6
  • 84
    Como se mencionó en otra respuesta, se puede hacer un truncado negativo seguro 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 cadenas en números enteros, si desea hacerlo)Keen 19/04/2013 a las 19:08
  • 5
    Votaría si esta respuesta tuviera un ejemplo de entrada / salida. J. Random Coder 27/08/15 a las 14:40
  • 8
    Con respecto al comentario ~~ limita el valor a enteros de 32 bits con signo, 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 28/03/2016 a las 15:27
  • 3
    Lea a continuación en varios lugares: Math.trunc(val);Comente porque esta es la respuesta aceptadaOld Badman Grey 5 de mayo de 2016 a las 6:05
  • 1
    No funciona con precisión exacta para valores como2.3 - 2.3 % 1Lapys 6/11/18 a las 23:31
321

Operador OR bit a bit

Se puede utilizar un operador or bit a bit para truncar cifras 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?

Creé una prueba JSPerf que compara el rendimiento entre:

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

eso solo funciona con números positivos. En este caso, es seguro utilizar las operaciones bit a bit, así como la Math.floorfunción.

Pero si necesita que su código funcione tanto con positivos como con 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 verificación adicional de signos, Math es ahora la más lenta de las cuatro.

Nota

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

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987
10
  • @FabioPoloni: sí super 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 emparejado por las operaciones NOT y Math, aunque las operaciones Math son las más lentas cuando también tiene que admitir números negativos, porque agrega una verificación adicional del signo numérico. Robert Koritnik 10 de enero de 2013 a las 13:54
  • 10
    @thefourtheye: todas las operaciones bit a bit, excepto el desplazamiento a la derecha sin signo, funcionan con enteros de 32 bits con signo. Por lo tanto, el uso de operaciones bit a bit en valores de punto flotante los convertirá en un entero eliminando los dígitos después del punto decimal. Robert Koritnik 2 de septiembre de 2013 a las 12:22
  • 3
    Si solo lo necesita para números positivos, Math.floor()es más rápido (al menos de acuerdo con 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 19/10/2013 a las 16:29
  • 8
    Tenga en cuenta que los operadores bit a bit operan en números de 32 bits. No funcionarán para números demasiado grandes para caber en 32 bits. Kat 31/10/13 a las 0:09
  • 2
    ~~es mejor porque es un operador unario. 4.2|0+4es igual 4pero ~~4.2+4es igual8Janus Troelsen 13/01/15 a las 18:10
98

Nota: No se puede usar Math.floor()como reemplazo de 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);
}
4
  • 1
    Eso depende del comportamiento deseado para los números negativos. Algunos usos necesitan números negativos para asignar al valor más negativo (-3,5 -> -4) y algunos requieren que se asignen al número entero más pequeño (-3,5 -> -3). El primero se denomina normalmente "suelo". La palabra "truncar" se usa a menudo para describir cualquier comportamiento. En mi caso, solo lo iba a alimentar con números negativos. Pero este comentario es una advertencia útil para aquellos que SI se preocupan por el comportamiento de números negativos. mcherm 16/10/09 a las 14:35
  • 28
    @mcherm: Entonces parece que no entienden el término "truncar" correctamente. Truncar hace exactamente lo que su nombre indica: trunca dígitos. Nunca es (en el sentido general) equivalente a suelo o techo. en.wikipedia.org/wiki/TruncationThanatos 16/04/12 a las 7:18
  • 5
    Math.trunc(value)fue agregado en ECMAScript 64esn0k 31 de julio de 2014 a las 5:49
  • 3
    floorredondea hacia -infinito, truncateredondea hacia cero. ( ceilredondea hacia + infinito). Peter Cordes 24/04/2017 a las 0:03
48

Se puede utilizar un operador not doble bit a bit para truncar flotantes. 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.

3
  • 1
    Esto probablemente sea algo malo para el código de producción (ya que es oscuro) pero era exactamente lo que necesitaba para codificar mi <canvas>motor de renderizado de fuentes en JS . ¡Gracias! Kragen Javier Sitaker 6 feb 12 a las 20:31
  • 10
    Esto también se puede lograr con n | 0.Jay Douglass 20 de marzo de 2012 a las 23:48
  • 18
    Tenga en cuenta que cualquiera de los métodos (~~ n o n | 0) solo funciona con 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 22/10/12 a las 18:36
41

Para truncar:

var intvalue = Math.floor(value);

Por ronda:

var intvalue = Math.round(value);
2
  • 6
    Math.floor no trunca los valores negativos. Vea la respuesta anterior. De lo contrario, buena respuesta. oligofren 4 de mayo de 2012 a las 14:47
  • Si está interesado en el rendimiento, he puesto un pequeño caso de prueba aquí: jsperf.com/dsafdgdfsaf/2 (var | 0 gana aquí). Cybolic 15/06/12 a las 23:54
26

Puede utilizar el método parseInt sin redondeo. Tenga cuidado con la entrada del usuario debido a las opciones de prefijo 0x (hexadecimal) y 0 (octal).

var intValue = parseInt(floatValue, 10);

EDITAR: como advertencia (de la sección de comentarios), tenga en cuenta que ciertos valores numéricos se convertirán a su forma exponencial, por ejemplo, lo 1e21que da como resultado la representación decimal incorrecta de"1"

6
  • 1
    Esto es realmente útil cuando solo desea la parte entera de un decimal, sin redondear hacia arriba o hacia abajo, que es lo que hacen .round, .ceil y .floor. Judah Gabriel Himango 30/01/12 a las 20:08
  • 1
    ... incluso cuando simplemente truncar este parece ser el método más lento. jsperf.com/float-to-int-conversion-comparisonRobert Koritnik 11/10/12 a las 10:34
  • 2
    Siempre pase el segundo valor a parseInt para especificar qué base está esperando. Entonces, parseInt (floatValue, 10) para obtener siempre la base 10.Tim Tisdall 22/0213 a las 16:52
  • 3
    Aunque esto es antiguo, esta pregunta parece ser una que se hace con bastante frecuencia, por lo que la pondré aquí como advertencia. Si el valor se representaría usando la notación "e" debido a su tamaño, solo resultará en 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 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 28 de noviembre de 2013 a las 2:04
  • 5
    @ Qantas94Heavy La razón de este comportamiento es porque parseInt()espera una cadena, no 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 9 de ene. De 2014 a las 20:56
19

Cambio de bit por 0 que es equivalente a la división por 1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2
3
  • 4
    Nota pequeña: >> 0parece funcionar solo para enteros < 2 ^ 31-1 y >>> 0para enteros < 2 ^ 32-1 . Esto devuelve 0 para valores más grandesRomuald Brunet 23 abr '14 a las 10:02
  • @RomualdBrunet, sí, JavaScript define claramente que todas las operaciones bit a bit funcionan con números de 32 bits. Eso está en las especificaciones. Alexis Wilke 24 de mayo de 2014 a las 2:51
  • Esto funciona ya que Javascript realiza operaciones bit a bit solo con enteros de 32 bits (con signo) como se indica en una respuesta anterior. Entonces, cualquier operación de bits que parezca 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 25/04/18 a las 11:14
12

En su caso, cuando desee una cadena al final (para insertar comas), también puede usar la Number.toFixed()función, sin embargo, esto realizará el redondeo.

7

Aquí hay muchas sugerencias. 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 usando el operador de módulo. Probablemente sea más fácil de entender que el bit a bit OR:

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
1
  • Si se refiere a otra respuesta, agregue una referencia o esboce brevemente su idea. bertl 11/07/2013 a las 14:06
7

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 https://jsfiddle.net/au51uj3r/

6

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

Para truncar :

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

Para redonda :

console.log(Math.round( 1.5 ));  // 2
console.log(Math.round( 1.49 )); // 1
console.log(Math.round( -1.6 )); // -2
console.log(Math.round( -1.3 )); // -1
0
3

Si observa el Mathobjeto nativo en JavaScript, obtendrá un montón de funciones para trabajar con 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 desea redondearlo al número más cercano, simplemente haga:

const rounded = Math.floor(myValue);

y obtienes:

56

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

const roundedUp = Math.ceil(myValue);

y obtienes:

57

Además, Math.roundredondearlo 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...

1
  • 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 16/10/19 a las 14:15
3

Rendimiento

Hoy 2020.11.28 realizo pruebas en MacOs HighSierra 10.13.6 en Chrome v85, Safari v13.1.2 y Firefox v80 para las soluciones elegidas.

Resultados

  • para todos los navegadores, todas las soluciones (excepto B y K) dan resultados de velocidad muy similares
  • las soluciones B y K son lentas

ingrese la descripción de la imagen aquí

Detalles

Realizo un caso de prueba que puedes ejecutar AQUÍ

El siguiente fragmento presenta las diferencias entre las soluciones A B C D E F G H I J K L

function A(float) {
    return Math.trunc( float );
}

function B(float) {
    return parseInt(float);
}

function C(float) {
    return float | 0;
}

function D(float) {
    return ~~float;
}

function E(float) {
    return float >> 0;
}

function F(float) {
    return float - float%1;
}

function G(float) {
    return float ^ 0;
}

function H(float) {
    return Math.floor( float );
}

function I(float) {
    return Math.ceil( float );
}

function J(float) {
    return Math.round( float );
}

function K(float) {
    return float.toFixed(0);
}

function L(float) {
    return float >>> 0;
}






// ---------
// TEST
// ---------

[A,B,C,D,E,F,G,H,I,J,K,L]
  .forEach(f=> console.log(`${f.name} ${f(1.5)} ${f(-1.5)} ${f(2.499)} ${f(-2.499)}`))
This snippet only presents functions used in performance tests - it not perform tests itself!

Y aquí hay resultados de ejemplo para Chrome.

ingrese la descripción de la imagen aquí

1

Solo quiero señalar que monetariamente desea redondear, y no trunc. Tener una diferencia de 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 proporciona el redondeo directo; su aplicación financiera puede requerirlo.

Redondeo gaussiano / bancario en JavaScript

0

Si está utilizando angularjs, entonces la solución simple es la siguiente en el enlace de plantillas HTML

{{val | number:0}}

convertirá val en entero

siga con este enlace docs.angularjs.org/api/ng/filter/number