Saltar al contenido

Truncar (no redondear) números decimales en javascript

Solución:

La respuesta de Dogbert es buena, pero si su código puede tener que lidiar con números negativos, Math.floor por sí solo puede dar resultados inesperados.

P.ej Math.floor(4.3) = 4, pero Math.floor(-4.3) = -5

Use una función auxiliar como esta en su lugar para obtener resultados consistentes:

truncateDecimals = function (number) {
    return Math[number < 0 ? 'ceil' : 'floor'](number);
};

// Applied to Dogbert's answer:
var a = 5.467;
var truncated = truncateDecimals(a * 100) / 100; // = 5.46

Aquí hay una versión más conveniente de esta función:

truncateDecimals = function (number, digits) {
    var multiplier = Math.pow(10, digits),
        adjustedNum = number * multiplier,
        truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum);

    return truncatedNum / multiplier;
};

// Usage:
var a = 5.467;
var truncated = truncateDecimals(a, 2); // = 5.46

// Negative digits:
var b = 4235.24;
var truncated = truncateDecimals(b, -2); // = 4200

Si ese no es el comportamiento deseado, inserte una llamada a Math.abs en la primera línea:

var multiplier = Math.pow(10, Math.abs(digits)),

EDITAR: shendz señala correctamente que el uso de esta solución con a = 17.56 producirá incorrectamente 17.55. Para obtener más información sobre por qué sucede esto, lea Lo que todo informático debe saber sobre la aritmética de coma flotante. Desafortunadamente, escribir una solución que elimine todas las fuentes de error de punto flotante es bastante complicado con javascript. En otro idioma, usarías enteros o tal vez un tipo decimal, pero con javascript …

Esta solución debiera ser 100% exacto, pero también será más lento:

function truncateDecimals (num, digits) {
    var numS = num.toString(),
        decPos = numS.indexOf('.'),
        substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
        trimmedResult = numS.substr(0, substrLength),
        finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;

    return parseFloat(finalResult);
}

Para aquellos que necesitan velocidad pero también quieren evitar errores de punto flotante, intente algo como BigDecimal.js. Puede encontrar otras bibliotecas Javascript BigDecimal en esta pregunta SO: “¿Existe una buena biblioteca Javascript BigDecimal?” y aquí hay una buena publicación de blog sobre bibliotecas matemáticas para Javascript

upd:

Entonces, después de todo, resultó que los errores de redondeo siempre lo perseguirán, sin importar cuánto intente compensarlos. Por tanto, el problema debe resolverse representando los números exactamente en notación decimal.

Number.prototype.toFixedDown = function(digits) {
    var re = new RegExp("(\d+\.\d{" + digits + "})(\d)"),
        m = this.toString().match(re);
    return m ? parseFloat(m[1]) : this.valueOf();
};

[   5.467.toFixedDown(2),
    985.943.toFixedDown(2),
    17.56.toFixedDown(2),
    (0).toFixedDown(1),
    1.11.toFixedDown(1) + 22];

// [5.46, 985.94, 17.56, 0, 23.1]

Solución antigua propensa a errores basada en la compilación de otras:

Number.prototype.toFixedDown = function(digits) {
  var n = this - Math.pow(10, -digits)/2;
  n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
  return n.toFixed(digits);
}

var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *