w3schools type ejemplo array javascript variables types

ejemplo - typeof javascript w3schools



¿Cuál es el mejor método para convertir el punto flotante en un entero en JavaScript? (12)

Existen varios métodos diferentes para convertir números de coma flotante a enteros en JavaScript. Mi pregunta es ¿qué método ofrece el mejor rendimiento, es más compatible o se considera la mejor práctica?

Aquí hay algunos métodos que conozco:

var a = 2.5; window.parseInt(a); // 2 Math.floor(a); // 2 a | 0; // 2

Estoy seguro de que hay otros por ahí. Sugerencias?


Al parecer, el doble bit a bit no es la forma más rápida de poner un número en el piso:

var x = 2.5; console.log(~~x); // 2

Solía ​​ser un artículo aquí, obteniendo un 404 ahora: http://james.padolsey.com/javascript/double-bitwise-not/

Google lo tiene en caché: http://74.125.155.132/search?q=cache:wpZnhsbJGt0J:james.padolsey.com/javascript/double-bitwise-not/+double+bitwise+not&cd=1&hl=en&ct=clnk&gl=us

¡Pero la máquina de Wayback salva el día! http://web.archive.org/web/20100422040551/http://james.padolsey.com/javascript/double-bitwise-not/


Así que hice un punto de referencia, en Chrome cuando la entrada ya es un número, el más rápido sería ~~num y num|0 , la mitad de la velocidad: Math.floor , y el más lento sería parseInt ver here

EDITAR : parece que ya hay otra persona que hizo el punto de referencia de rounding (más resultado) y ways adicionales: num>>0 (tan rápido como |0 ) y num - num%1 (a veces rápido)


De "Javascript: The Good Parts" de Douglas Crockford:

Number.prototype.integer = function () { return Math[this < 0 ? ''ceil'' : ''floor''](this); }

Al hacerlo, estás agregando un método a cada objeto Number.

Entonces puedes usarlo así:

var x = 1.2, y = -1.2; x.integer(); // 1 y.integer(); // -1 (-10 / 3).integer(); // -3


De acuerdo con este sitio web :

parseInt se utiliza ocasionalmente como un medio para convertir un número de coma flotante en un número entero. Es muy inadecuado para esa tarea porque si su argumento es de tipo numérico, primero se convertirá en una cadena y luego se analizará como un número ...

Para redondear números a números enteros, uno de Math.round, Math.ceil y Math.floor son preferibles ...


La ''mejor'' manera depende de:

  • modo de redondeo: qué tipo de redondeo (del flotador a entero) espera / requiere
    para números positivos y / o negativos que tienen una parte fraccionaria.
    Ejemplos comunes:

    float | trunc | floor | ceil | near (half up) ------+-------+-------+-------+--------------- +∞ | +∞ | +∞ | +∞ | +∞ +2.75 | +2 | +2 | +3 | +3 +2.5 | +2 | +2 | +3 | +3 +2.25 | +2 | +2 | +3 | +2 +0 | +0 | +0 | +0 | +0 NaN | NaN | NaN | NaN | NaN -0 | -0 | -0 | -0 | -0 -2.25 | -2 | -3 | -2 | -2 -2.5 | -2 | -3 | -2 | -2 -2.75 | -2 | -3 | -2 | -3 -∞ | -∞ | -∞ | -∞ | -∞ Para las conversiones de flotante a entero, comúnmente esperamos un "truncamiento"
    (también conocido como "redondear hacia cero" o "redondear lejos del infinito" ).
    Efectivamente, esto simplemente ''corta'' la parte fraccionaria de un número de punto flotante.
    La mayoría de las técnicas y los métodos internos (internos) se comportan de esta manera.

  • entrada: cómo se representa su número (punto flotante):
    • String
      Comúnmente base / base: 10 (decimal)
    • punto flotante (''interno'') Number
  • salida: lo que quiere hacer con el valor resultante:
    • String salida (intermedia) (base predeterminada 10) (en la pantalla)
    • realizar más cálculos sobre el valor resultante
  • distancia:
    en qué rango numérico esperas entrada / cálculo-resultados
    y para qué rango espera salida correspondiente ''correcta''.

¡Solo después de que se hayan respondido estas consideraciones, podemos pensar en los métodos apropiados y la velocidad!

Según la especificación ECMAScript 262: todos los números (tipo de Number ) en javascript se representan / almacenan en:
Formato " Doble punto flotante de precisión IEEE 754 (binary64) ".
Por lo tanto, los enteros también se representan en el mismo formato de coma flotante (como números sin una fracción).
Nota: ¡la mayoría de las implementaciones usan internamente tipos de enteros más eficientes (para velocidad y tamaño de memoria) cuando es posible!

Como este formato almacena 1 bit de signo, 11 bits de exponente y los primeros 53 bits significativos ("mantisa"), podemos decir que: solo los valores Number entre -2 52 y +2 52 pueden tener una fracción.
En otras palabras: todos los valores Number positivos y negativos representables entre 2 52 y (casi) 2 (2 11 /2=1024) (en cuyo punto el formato lo llama un día Infinity ) ya son enteros (redondeados internamente, ya que no quedan bits para representar los dígitos enteros fraccionarios y / o menos significativos restantes).

Y está el primer ''gotcha'':
No puede controlar el modo de redondeo interno de Number -resultados para las conversiones incorporadas de Literal / Cadena a flotación (modo de redondeo: IEEE 754-2008 "redondear al más cercano, vincular a par") y operaciones aritméticas incorporadas ( rounding-mode: IEEE 754-2008 "redondo a más cercano").
Por ejemplo:
2 52 +0.25 = 4503599627370496.25 se redondea y se almacena como: 4503599627370496
2 52 +0.50 = 4503599627370496.50 se redondea y almacena como: 4503599627370496
2 52 +0.75 = 4503599627370496.75 se redondea y se almacena como: 4503599627370497
2 52 +1.25 = 4503599627370497.25 se redondea y se almacena como: 4503599627370497
2 52 +1.50 = 4503599627370497.50 se redondea y se almacena como: 4503599627370498
2 52 +1.75 = 4503599627370497.75 se redondea y se almacena como: 4503599627370498
2 52 +2.50 = 4503599627370498.50 se redondea y se almacena como: 4503599627370498
2 52 +3.50 = 4503599627370499.50 se redondea y almacena como: 4503599627370500

Para controlar el redondeo, su Number necesita una parte fraccionaria (y al menos un bit para representarlo); de lo contrario, ceil / floor / trunc / near devuelve el entero que introdujo en él.

Para ceil / floor / trunc correctamente un Número hasta x dígito (s) decimal (es) decimal (es) significativo (s), solo nos importa si el valor decimal inferior más alto y más alto nos dará un valor fraccionario binario después del redondeo (para que no quede bloqueado o el siguiente entero).
Entonces, por ejemplo, si espera un redondeo "correcto" (para ceil / piso / trunc) de hasta 1 dígito decimal fraccionario significativo ( x.1 to x.9 ), necesitamos al menos 3 bits (no 4) para darnos un valor fraccionario binario:
0.1 está más cerca de 1/(2 3 =8)=0.125 que de 0 y 0.9 está más cerca de 1-1/(2 3 =8)=0.875 que de 1 .

solo hasta ±2 (53-3=50) todos los valores representables tendrán una fracción binaria distinta de cero para no más que el primer dígito decimal decimal significativo (valores x.1 a x.9 ).
Para 2 decimales ±2 (53-6=47) , para 3 decimales ±2 (53-9=44) , para 4 decimales ±2 (53-13=40) , para 5 decimales ±2 (53-16=37) , para 6 decimales ±2 (53-19=34) , para 7 decimales ±2 (53-23=30) , para 8 decimales ±2 (53-26=27) , para 9 decimales ±2 (53-29=24) , por 10 decimales ±2 (53-33=20) , por 11 decimales ±2 (53-36=17) , etc.

Un "Entero seguro" en javascript es un número entero:

  • que se puede representar exactamente como un número de doble precisión IEEE-754, y
  • cuya representación IEEE-754 no puede ser el resultado de redondear cualquier otro entero para ajustarse a la representación IEEE-754
    (aunque ±2 53 (como potencia exacta de 2) puede representarse exactamente, no es un entero seguro porque también podría haber sido ±(2 53 +1) antes de redondearse para ajustarse al máximo de 53 más bits significativos).

Esto define efectivamente un rango de subconjuntos de enteros (representables de forma segura) entre -2 53 y +2 53 :

  • desde: -(2 53 - 1) = -9007199254740991 (inclusive)
    (una constante proporcionada como propiedad estática Number.MIN_SAFE_INTEGER desde ES6)
  • a: +(2 53 - 1) = +9007199254740991 (inclusive)
    (una constante proporcionada como propiedad estática Number.MAX_SAFE_INTEGER desde ES6)
    Polyfill trivial para estas 2 nuevas constantes ES6:

    Number.MIN_SAFE_INTEGER || (Number.MIN_SAFE_INTEGER= -(Number.MAX_SAFE_INTEGER=9007199254740991) //Math.pow(2,53)-1 );


Desde ES6 también hay un método estático complementario Number.isSafeInteger() que prueba si el valor pasado es de tipo Number y es un entero dentro del rango entero seguro (devolviendo un booleano true o false ).
Nota: también devolverá false para: NaN , Infinity y obviamente String (incluso si representa un número).
Ejemplo de Polyfill:

Number.isSafeInteger || (Number.isSafeInteger = function(value){ return typeof value === ''number'' && value === Math.floor(value) && value < 9007199254740992 && value > -9007199254740992; });

ECMAScript 2015 / ES6 proporciona un nuevo método estático Math.trunc()
para truncar un flotante en un entero:

Devuelve la parte integral del número x, eliminando cualquier dígito fraccionario. Si x ya es un número entero, el resultado es x.

O ponlo más simple ( MDN ):

A diferencia de otros tres métodos matemáticos: Math.floor() , Math.ceil() y Math.round() , la forma en que Math.trunc() funciona es muy simple y directa:
simplemente trunque el punto y los dígitos detrás de él, sin importar si el argumento es un número positivo o negativo.

Podemos explicar (y Math.trunc() ) Math.trunc() como tal:

Math.trunc || (Math.trunc = function(n){ return n < 0 ? Math.ceil(n) : Math.floor(n); });

Tenga en cuenta que la carga útil del polyfill anterior puede ser mejor pre-optimizada por el motor en comparación con:
Math[n < 0 ? ''ceil'' : ''floor''](n);

Uso : Math.trunc(/* Number or String */)
Entrada : (número entero o punto flotante) Number (pero intentaremos convertir una cadena a un número felizmente)
Salida : Number (entero) (pero intentará felizmente convertir Número a cadena en un contexto de cadena)
Rango : -2^52 a +2^52 (más allá de esto deberíamos esperar ''errores de redondeo'' (y en algún punto notación científica / exponencial) simple y simplemente porque nuestra entrada de Number en IEEE 754 ya perdió precisión fraccional: desde Números entre ±2^52 a ±2^53 ya son enteros redondeados internamente (por ejemplo, 4503599627370509.5 ya está internamente representado como 4503599627370510 ) y más allá de ±2^53 los enteros también pierden precisión (potencias de 2)).

Conversión de flotante a entero restando el Remainder ( % ) de una devision por 1 :

Ejemplo: result = nn%1 (o n-=n%1 )
Esto también debería truncar las carrozas. Como el operador Resto tiene una precedence más alta que la Resta, obtenemos efectivamente: (n)-(n%1) .
Para Números positivos es fácil ver que esto nivela el valor: (2.5) - (0.5) = 2 ,
para Números negativos, esto cela el valor: (-2.5) - (-0.5) = -2 (porque --=+ tan (-2.5) + (0.5) = -2 ).

Dado que la entrada y la salida son Number , deberíamos obtener el mismo rango útil y la misma producción en comparación con ES6 Math.trunc() (o su Math.trunc() ).
Nota: difícil, me temo (no estoy seguro), puede haber diferencias: porque estamos haciendo aritmética (que internamente usa el modo de redondeo "nearTiesEven" (también conocido como Banker''s Rounding)) en el Número original (el flotante) y un segundo Número derivado (la fracción ) esto parece invitar a la composición digital de la representación y los errores de redondeo aritmético, por lo tanto, potencialmente devolver un flotador después de todo ..

Conversión de flotante a entero mediante (ab-) usando operaciones bit a bit :

Esto funciona forzando internamente una conversión de Number (punto flotante) (truncamiento y desbordamiento) a un valor entero de 32 bits con signo (complemento a dos) mediante el uso de una operación bit a bit en un Number (y el resultado se convierte a a (punto flotante) Number que contiene solo el valor entero).

Nuevamente, la entrada y la salida son Number (y nuevamente conversión silenciosa de Entrada de cadena a Número y Salida de número a Cadena).

Más importante resistente (y generalmente olvidado y no explicado):
dependiendo del funcionamiento a nivel de bit y el signo del número , el rango útil estará limitado entre:
-2^31 a +2^31 (como ~~num o num|0 o num>>0 ) O 0 a +2^32 ( num>>>0 ).

Esto debería aclararse con la siguiente tabla de búsqueda (que contiene todos los ejemplos "críticos"):

n | n>>0 OR n<<0 OR | n>>>0 | n < 0 ? -(-n>>>0) : n>>>0 | n|0 OR n^0 OR ~~n | | | OR n&0xffffffff | | ----------------------------+-------------------+-------------+--------------------------- +4294967298.5 = (+2^32)+2.5 | +2 | +2 | +2 +4294967297.5 = (+2^32)+1.5 | +1 | +1 | +1 +4294967296.5 = (+2^32)+0.5 | 0 | 0 | 0 +4294967296 = (+2^32) | 0 | 0 | 0 +4294967295.5 = (+2^32)-0.5 | -1 | +4294967295 | +4294967295 +4294967294.5 = (+2^32)-1.5 | -2 | +4294967294 | +4294967294 etc... | etc... | etc... | etc... +2147483649.5 = (+2^31)+1.5 | -2147483647 | +2147483649 | +2147483649 +2147483648.5 = (+2^31)+0.5 | -2147483648 | +2147483648 | +2147483648 +2147483648 = (+2^31) | -2147483648 | +2147483648 | +2147483648 +2147483647.5 = (+2^31)-0.5 | +2147483647 | +2147483647 | +2147483647 +2147483646.5 = (+2^31)-1.5 | +2147483646 | +2147483646 | +2147483646 etc... | etc... | etc... | etc... +1.5 | +1 | +1 | +1 +0.5 | 0 | 0 | 0 0 | 0 | 0 | 0 -0.5 | 0 | 0 | 0 -1.5 | -1 | +4294967295 | -1 etc... | etc... | etc... | etc... -2147483646.5 = (-2^31)+1.5 | -2147483646 | +2147483650 | -2147483646 -2147483647.5 = (-2^31)+0.5 | -2147483647 | +2147483649 | -2147483647 -2147483648 = (-2^31) | -2147483648 | +2147483648 | -2147483648 -2147483648.5 = (-2^31)-0.5 | -2147483648 | +2147483648 | -2147483648 -2147483649.5 = (-2^31)-1.5 | +2147483647 | +2147483647 | -2147483649 -2147483650.5 = (-2^31)-2.5 | +2147483646 | +2147483646 | -2147483650 etc... | etc... | etc... | etc... -4294967294.5 = (-2^32)+1.5 | +2 | +2 | -4294967294 -4294967295.5 = (-2^32)+0.5 | +1 | +1 | -4294967295 -4294967296 = (-2^32) | 0 | 0 | 0 -4294967296.5 = (-2^32)-0.5 | 0 | 0 | 0 -4294967297.5 = (-2^32)-1.5 | -1 | +4294967295 | -1 -4294967298.5 = (-2^32)-2.5 | -2 | +4294967294 | -2

Nota 1: la última columna tiene un rango extendido de 0 a -4294967295 usando (n < 0 ? -(-n>>>0) : n>>>0) .
Nota 2: bitwise introduce su propia conversión: sobrecarga ( s ) (la gravedad frente a Math depende de la implementación real, por lo que el bitwise podría ser más rápido (a menudo en navegadores históricos más antiguos)).

Obviamente, si su número de ''coma flotante'' era una String para empezar,
parseInt(/*String*/, /*Radix*/) sería una opción apropiada para analizarlo en un número entero.
parseInt() se truncará también (para números positivos y negativos).
El rango está nuevamente limitado al punto flotante de doble precisión IEEE 754 como se explicó anteriormente para el (los) método (s) Math (s).

Finalmente, si tienes un String y esperas un String como resultado, también puedes cortar el punto y la fracción del radix (lo que también te proporciona un rango de truncamiento más grande comparado con el punto flotante de doble precisión IEEE 754 ( ±2^52 )).

EXTRA:
De la información anterior, ahora debería tener todo lo que necesita saber.

Si, por ejemplo, desea redondear desde cero (también conocido como redondeado hacia el infinito ) puede modificar el polyfill Math.trunc() , por ejemplo :

Math.intToInf || (Math.intToInf = function(n){ return n < 0 ? Math.floor(n) : Math.ceil(n); });


La pregunta parece estar preguntando específicamente sobre la conversión de un flotante a un int. toFixed entendido, la forma de hacerlo es utilizar para toFixed . Asi que...

var myFloat = 2.5; var myInt = myFloat.toFixed(0);

¿Alguien sabe si Math.floor() tiene más o menos rendimiento que Number.toFixed() ?


La respuesta ya ha sido dada, pero solo para ser claro.

Usa la biblioteca de Matemáticas para esto. funciones de ronda, ceil o piso.

parseInt es para convertir una cadena a un int que no es lo que se necesita aquí

toFixed es para convertir un flotador en una cadena que tampoco es lo que se necesita aquí

Dado que las funciones de Matemáticas no harán ninguna conversión ao desde una cadena, será más rápido que cualquiera de las otras opciones que de todos modos son incorrectas.


Puede usar el Número (a) .aFija (0);

O incluso simplemente a.toFixed (0);

Editar:

Eso está redondeando a 0 lugares, ligeramente diferente que truncar, y como alguien más sugirió, toFixed devuelve una cadena, no un entero sin procesar. Útil para propósitos de exhibición.

var num = 2.7; // typeof num is "Number" num.toFixed(0) == "3"


Usando operadores bit a bit. Puede que no sea la forma más clara de convertir a un número entero, pero funciona en cualquier tipo de tipo de datos.

Supongamos que su función toma un value argumento, y la función funciona de tal manera que el value siempre debe ser un número entero (y se acepta 0). A continuación, cualquiera de los siguientes asignará value como un entero:

value = ~~(value) value = value | 0; value = value & 0xFF; // one byte; use this if you want to limit the integer to // a predefined number of bits/bytes

La mejor parte es que esto funciona con cadenas (lo que puede obtener de una entrada de texto, etc.) que son números ~~("123.45") === 123 . Cualquier valor no numérico da como resultado 0 , es decir,

~~(undefined) === 0 ~~(NaN) === 0 ~~("ABC") === 0

Funciona con números hexadecimales como cadenas (con un prefijo 0x )

~~("0xAF") === 175

Supongo que hay algún tipo de coerción involucrado. Haré algunas pruebas de rendimiento para compararlas con parseInt() y Math.floor() , pero me gusta tener la conveniencia adicional de no lanzar Errors y obtener un 0 para no-números.


parseInt () es probablemente el mejor. a | 0 a | 0 no hace lo que realmente quiere (simplemente asigna 0 si a es un valor indefinido o nulo, lo que significa que un objeto vacío o una matriz pasa la prueba), y Math.floor funciona mediante algún truco tipo (básicamente llama a parseInt ( ) en el fondo).


también podrías hacerlo de esta manera:

var string = ''1''; var integer = a * 1;


var i = parseInt(n, 10);

Si no especifica una raíz, los valores como ''010'' se tratarán como octales (y el resultado será 8 no 10 ).