Pregunta

En JavaScript, la forma típica de redondear un número a N Decimal Places es algo así:

function roundNumber(num, dec) {
  return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
}

function roundNumber(num, dec) {
  return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
}

console.log(roundNumber(0.1 + 0.2, 2));
console.log(roundNumber(2.1234, 2));

Sin embargo, este enfoque volverá a un máximo de n lugares decimales mientras quiero siempre Redondea a N Decimal Places. Por ejemplo, "2.0" sería redondeado a "2".

¿Algunas ideas?

¿Fue útil?

Solución

Eso no es un problema de redondeo, ese es un problema de visualización. Un número no contiene información sobre dígitos significativos; El valor 2 es el mismo que 2.0000000000000. Es cuando convierte el valor redondeado en una cadena que ha hecho que muestre un cierto número de dígitos.

Podrías agregar ceros después del número, algo así como:

var s = number.toString();
if (s.indexOf('.') == -1) s += '.';
while (s.length < s.indexOf('.') + 4) s += '0';

(Tenga en cuenta que esto supone que la configuración regional del cliente usa el período como separador decimal, el código necesita más trabajo para funcionar para otras configuraciones).

Otros consejos

Creo que hay un enfoque más simple para todos los que se dan aquí, y es el método. Number.toFixed() ya implementado en JavaScript.

Simplemente escriba:

var myNumber = 2;

myNumber.toFixed(2); //returns "2.00"
myNumber.toFixed(1); //returns "2.0"

etc...

Encontre un camino. Este es el código de Christoph con una solución:

function toFixed(value, precision) {
    var precision = precision || 0,
        power = Math.pow(10, precision),
        absValue = Math.abs(Math.round(value * power)),
        result = (value < 0 ? '-' : '') + String(Math.floor(absValue / power));

    if (precision > 0) {
        var fraction = String(absValue % power),
            padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
        result += '.' + padding + fraction;
    }
    return result;
}

Lea los detalles de repetir un personaje usando un constructor de matriz aquí Si tiene curiosidad por qué agregué el "+ 1".

Siempre hay una mejor manera de hacer las cosas.

var number = 51.93999999999761;

Me gustaría obtener cuatro dígitos de precisión: 51.94

solo haz:

number.toPrecision(4);

El resultado será: 51.94

Método de redondeo similar a PHP

El siguiente código se puede usar para agregar su propia versión de Math.round a su propio espacio de nombres que toma un parámetro de precisión. A diferencia del redondeo decimal en el ejemplo anterior, esto no realiza una conversión hacia y desde las cuerdas, y el parámetro de precisión funciona de la misma manera que PHP y Excel, por lo que un positivo 1 redondearía a 1 lugar decimal y -1 redondear a las decenas.

var myNamespace = {};
myNamespace.round = function(number, precision) {
    var factor = Math.pow(10, precision);
    var tempNumber = number * factor;
    var roundedTempNumber = Math.round(tempNumber);
    return roundedTempNumber / factor;
};

myNamespace.round(1234.5678, 1); // 1234.6
myNamespace.round(1234.5678, -1); // 1230

de Referencia de desarrollador de Mozilla para Math.round ()

Esperemos que el código de trabajo (no hiciera muchas pruebas):

function toFixed(value, precision) {
    var precision = precision || 0,
        neg = value < 0,
        power = Math.pow(10, precision),
        value = Math.round(value * power),
        integral = String((neg ? Math.ceil : Math.floor)(value / power)),
        fraction = String((neg ? -value : value) % power),
        padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');

    return precision ? integral + '.' +  padding + fraction : integral;
}

Esto funciona para redondear a n dígitos (si solo desea truncar a n dígitos, elimine la llamada matemática.

function roundN(value, digits) {
   var tenToN = 10 ** digits;
   return /*Math.trunc*/(Math.round(value * tenToN)) / tenToN;
}

Tuve que recurrir a tal lógica en Java en el pasado cuando estaba autorizando componentes de la manipulación de datos de la manipulación de datos. Esto es desde que descubrí que agregar 0.1 muchas veces a 0 terminaría con una parte decimal inesperadamente larga (esto se debe a la aritmética del punto flotante).

Un comentario de usuario en Número de formato para mostrar siempre 2 decimales llama a esta técnica de escala.

Algunos mencionan que hay casos que no redondean como se esperaba y en http://www.jacklmoore.com/notes/rounding-in-javascript/ Esto se sugiere en su lugar:

function round(value, decimals) {
  return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}

Aquí hay un enlace a un JavaScript Sprintf,

http://www.webtoolkit.info/javascript-sprintf.html

Una llamada a sprintf () es una metodología de redondeo en Perl, pero JavaScript no tiene esa función de forma nativa.

http://perdoc.perl.org/functions/sprintf.html

¿Eso ayuda?

Creo que la función a continuación puede ayudar

function roundOff(value,round) {
   return (parseInt(value * (10 ** (round + 1))) - parseInt(value * (10 ** round)) * 10) > 4 ? (((parseFloat(parseInt((value + parseFloat(1 / (10 ** round))) * (10 ** round))))) / (10 ** round)) : (parseFloat(parseInt(value * (10 ** round))) / ( 10 ** round));
}

Uso: roundOff(600.23458,2); Volverá 600.23

Si realmente no le importa el redondeo, simplemente agregue un tofijo (x) y luego elimine los 0ES y el punto si es necesario. No es una solución rápida.

function format(value, decimals) {
    if (value) {
        value = value.toFixed(decimals);            
    } else {
        value = "0";
    }
    if (value.indexOf(".") < 0) { value += "."; }
    var dotIdx = value.indexOf(".");
    while (value.length - dotIdx <= decimals) { value += "0"; } // add 0's

    return value;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top