JavaScript: se redondea a varios lugares decimales, pero se eliminan los ceros adicionales

85

Aquí está el escenario: estoy recibiendo .9999999999999999cuando debería estar recibiendo 1.0.
Puedo permitirme perder un lugar decimal de precisión, así que estoy usando .toFixed(15), qué tipo de funciona.

El redondeo funciona, pero el problema es que me dan 1.000000000000000.
¿Hay alguna manera de redondear a varios lugares decimales, pero eliminar los espacios en blanco adicionales?

Nota: .toPrecisionno es lo que quiero; Solo quiero especificar cuántos números después del punto decimal.
Nota 2: No puedo usar simplemente .toPrecision(1)porque necesito mantener la alta precisión para los números que realmente tienen datos después del punto decimal. Idealmente, habría exactamente tantos lugares decimales como sea necesario (hasta 15).

Nathan
fuente
El punto es que .toFixed devuelve una Cadena, por lo que simplemente hacer un recorrido de ida y vuelta a través de un Número y luego volver a una Cadena lo reconvertirá sin los ceros finales.
Neil
@Nathan: solo para una aclaración. ¿Solo desea eliminar los ceros finales en la cadena que obtuvo con toFixed ()?
Jiri Kriz

Respuestas:

141
>>> parseFloat(0.9999999.toFixed(4));
1
>>> parseFloat(0.0009999999.toFixed(4));
0.001
>>> parseFloat(0.0000009999999.toFixed(4));
0
Gus
fuente
4
No olvide ponerlos entre paréntesis cuando trate números negativos: -2.34.toFixed(1)retorna -2.3debido a la precedencia del operador .
Константин Ван
1
Usar el operador unario + debería ser más rápido que la parseFloatfunción: +number.toFixed(13)esta expresión también se puede usar para eliminar imprecisiones de números de JavaScript como en 1.0000000000000045.
ygoe
37

Sí, hay una manera. Utilice parseFloat().

parseFloat((1.005).toFixed(15)) //==> 1.005
parseFloat((1.000000000).toFixed(15)) //==> 1

Vea un ejemplo en vivo aquí: http://jsfiddle.net/nayish/7JBJw/

Nachshon Schwartz
fuente
1
No funciona parseFloat("0.0000007"), lo que da"7e-7"
Matt Huggins
19

Según tengo entendido, desea eliminar los ceros finales en la cadena que obtuvo a través de toFixed(). Esta es una operación de cadena pura:

var x = 1.1230000;
var y = x.toFixed(15).replace(/0+$/, "");  // ==> 1.123
Jiri Kriz
fuente
6
Eres el único que realmente respondió la pregunta ... ¡gracias!
Mugen
4
Esto deja el punto en números redondos ("100.00" => "100.")
pastilla
5
@pckill si no desea que el punto pueda incluirlo en la expresión regular para ser reemplazado ( ...replace(/\.?0+$/, "");).
Zach Snow
Eso falla en 0 y -0 porque se 0convierte en la cadena vacía "", y se -0convierte en -, ninguno de los cuales se espera (supongo). @ zach-snow su solución sugerida también falla en 0 y -0.
robocat
@Mugen, ¿cuál fue el problema con la respuesta de Gus?
Trysis
9

Number(n.toFixed(15)) or +(n.toFixed(15)) convertirá la cadena decimal de 15 posiciones en un número, eliminando los ceros finales.

Kennebec
fuente
1
Pensé en señalarlo, + (n.toFixed (...)) es mucho más eficiente que parseFloat. No estoy seguro de por qué, pero también es más eficiente que Number en Chrome.
Domino
8

Si lanza el valor de retorno a un número, esos ceros finales se eliminarán. Esto también es menos detallado de lo que parseFloat()es.

+(4.55555).toFixed(2);
//-> 4.56

+(4).toFixed(2);
//-> 4

Este utiliza el operador unario + , por lo que si se utiliza esto como parte de una operación de cadena es necesario tener un infijo + antes de que: var n=0.9999999999999999; console.log('output ' + +n.toFixed(2));. FYI un unario + delante de una cadena lo convierte en un Número. Desde MDN: Unary + puede:

convertir representaciones de cadena de números enteros y flotantes, así como los valores que no son de cadena verdadero, falso y nulo. Se admiten enteros en formato decimal y hexadecimal (prefijo "0x"). Se admiten números negativos (aunque no para hexadecimal). Si no puede analizar un valor en particular, se evaluará como NaN.

CJ
fuente
@robocat Acabo de hacer una simple comprobación; +(4.1).toFixed(4)está 4.1en Chrome 60 .
Константин Ван
No lo entiendo. ¿Cuál fue la razón por la que esta respuesta fue rechazada?
Константин Ван
@K Tenías razón, así que eliminé mi comentario anterior y lo agregué a la respuesta (creo que estaba usando infijo + con una cadena en lhs, en lugar de usar correctamente unario +. ¡Por lo general, soy más cuidadoso! Saludos)
robocat
Esta respuesta todavía funciona con NaN, Infinity, -Infinity, 3e30 y 0. Algunas otras respuestas fallan en algunos casos de esquina.
robocat
(4) .toFixed (2) -> "4.00" en Chrome 60.0.3112.113
Daniel Que
1

Ninguno de estos realmente me consiguió lo que estaba buscando según el título de la pregunta, que era, por ejemplo, que 5.00 fuera 5 y 5.10 fuera 5.1. Mi solución fue la siguiente:

num.toFixed(places).replace(/\.?0+$/, '')

'5.00'.replace(/\.?0+$/, '') // 5
'5.10'.replace(/\.?0+$/, '') // 5.1
'5.0000001'.replace(/\.?0+$/, '') // 5.0000001
'5.0001000'.replace(/\.?0+$/, '') // 5.0001

Nota: la expresión regular solo funciona si places > 0

PD https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed

Jenna Zeigen
fuente
Falla 5e30(cambia el número a 5e3). ¡Los casos de esquina son diabólicos!
robocat
0

Hay un método mejor que mantiene la precisión y también elimina los ceros. Esto requiere un número de entrada y, a través de un poco de magia, sacará los ceros finales. Descubrí que 16 es el límite de precisión para mí, lo cual es bastante bueno si no colocas un satélite en Plutón.

function convertToFixed(inputnum)
{

      var mynum = inputnum.toPrecision(16);
//If you have a string already ignore this first line and change mynum.toString to the inputnum

      var mynumstr = mynum.toString();
    return parseFloat(mynumstr);
    }
    alert(convertToFixed(6.6/6));
Kevrone
fuente
0

El toFixed()método formatea a numberusando notación de punto fijo y devuelve a string.

Aplica una estrategia de redondeo a la mitad .

(0.124).toFixed(2); // returns 0.12
(0.125).toFixed(2); // returns 0.13

Como describió, de hecho también resultará en ceros finales (potencialmente innecesarios) a veces.

(0.001).toFixed(2); // returns 0.00

Es posible que no desee deshacerse de esos ceros finales, esencialmente podría convertirlo de nuevo a number. Hay muchas maneras de hacer esto.

+(0.001).toFixed(2); // the shortest

Para obtener una descripción general de los diferentes métodos para convertir cadenas en números, consulte esta pregunta, que tiene excelentes respuestas.

bvdb
fuente