redondear - sumar decimales javascript
Formato de un número con exactamente dos decimales en JavaScript (28)
toFixed (n) proporciona n longitud después del punto decimal; toPrecision (x) proporciona x longitud total.
Utilice este método a continuación
// Example: toPrecision(4) when the number has 7 digits (3 before, 4 after)
// It will round to the tenths place
num = 500.2349;
result = num.toPrecision(4); // result will equal 500.2
Y si quieres que el número sea fijo usa
result = num.toFixed(2);
Tengo esta línea de código que redondea mis números a dos decimales. Pero obtengo números como este: 10.8, 2.4, etc. Esta no es mi idea de dos decimales, ¿cómo puedo mejorar lo siguiente?
Math.round(price*Math.pow(10,2))/Math.pow(10,2);
Quiero números como 10.80, 2.40, etc. El uso de jQuery está bien conmigo.
100% trabajando !!! Intentalo
<html>
<head>
<script>
function replacePonto(){
var input = document.getElementById(''qtd'');
var ponto = input.value.split(''.'').length;
var slash = input.value.split(''-'').length;
if (ponto > 2)
input.value=input.value.substr(0,(input.value.length)-1);
if(slash > 2)
input.value=input.value.substr(0,(input.value.length)-1);
input.value=input.value.replace(/[^0-9.-]/,'''');
if (ponto ==2)
input.value=input.value.substr(0,(input.value.indexOf(''.'')+3));
if(input.value == ''.'')
input.value = "";
}
</script>
</head>
<body>
<input type="text" id="qtd" maxlength="10" style="width:140px" onkeyup="return replacePonto()">
</body>
</html>
@heridev y yo creamos una pequeña función en jQuery.
Puedes probar a continuación:
HTML
<input type="text" name="one" class="two-digits"><br>
<input type="text" name="two" class="two-digits">
jQuery
// apply the two-digits behaviour to elements with ''two-digits'' as their class
$( function() {
$(''.two-digits'').keyup(function(){
if($(this).val().indexOf(''.'')!=-1){
if($(this).val().split(".")[1].length > 2){
if( isNaN( parseFloat( this.value ) ) ) return;
this.value = parseFloat(this.value).toFixed(2);
}
}
return this; //for chaining
});
});
DEMO ONLINE:
Aquí está mi solución de 1 línea: Number((yourNumericValueHere).toFixed(2));
Esto es lo que sucede:
1) Primero, aplique .toFixed(2)
en el número del cual desea redondear los decimales. Tenga en cuenta que esto convertirá el valor a una cadena de número. Por lo tanto, si está utilizando Typescript, producirá un error como este:
"El tipo ''cadena'' no se puede asignar al tipo ''número''"
2) Para recuperar el valor numérico o para convertir la cadena en valor numérico, simplemente aplique la función Number()
en el llamado valor de "cadena".
Para aclaración, mira el siguiente ejemplo:
EJEMPLO: Tengo una cantidad que tiene hasta 5 dígitos en los lugares decimales y me gustaría acortarla a 2 lugares decimales. Lo hago así:
var price = 0.26453;
var priceRounded = Number((price).toFixed(2));
console.log(''Original Price: '' + price);
console.log(''Price Rounded: '' + priceRounded);
Aquí hay una simple
function roundFloat(num,dec){
var d = 1;
for (var i=0; i<dec; i++){
d += "0";
}
return Math.round(num * d) / d;
}
Use como alert(roundFloat(1.79209243929,4));
Con estos ejemplos, aún obtendrá un error al intentar redondear el número 1.005, la solución es utilizar una biblioteca como Math.js o esta función:
function round(value: number, decimals: number) {
return Number(Math.round(value + ''e'' + decimals) + ''e-'' + decimals);
}
El problema con los valores de punto flotante es que intentan representar una cantidad infinita de valores (continuos) con una cantidad fija de bits. Así que, naturalmente, debe haber alguna pérdida en el juego, y vas a ser mordido con algunos valores.
Cuando una computadora almacena 1.275 como un valor de punto flotante, en realidad no recordará si era 1.275 o 1.27499999999999993, o incluso 1.27500000000000002. Estos valores deberían dar resultados diferentes después de redondear a dos decimales, pero no lo harán, ya que para la computadora se ven exactamente iguales después de almacenarse como valores de punto flotante, y no hay manera de restaurar los datos perdidos. Cualquier cálculo adicional solo acumulará tal imprecisión.
Por lo tanto, si la precisión es importante, debe evitar los valores de punto flotante desde el principio. Las opciones más simples son
- usar una biblioteca dedicada
- usar cadenas para almacenar y pasar los valores (acompañado de operaciones de cadena)
- use números enteros (por ejemplo, podría pasar alrededor de la centésima parte de su valor real, por ejemplo, la cantidad en centavos en lugar de la cantidad en dólares)
Por ejemplo, cuando se usan enteros para almacenar el número de centésimas, la función para encontrar el valor real es bastante simple:
function descale(num, decimals) {
var hasMinus = num < 0;
var numString = Math.abs(num).toString();
var precedingZeroes = '''';
for (var i = numString.length; i <= decimals; i++) {
precedingZeroes += ''0'';
}
numString = precedingZeroes + numString;
return (hasMinus ? ''-'' : '''')
+ numString.substr(0, numString.length-decimals)
+ ''.''
+ numString.substr(numString.length-decimals);
}
alert(descale(127, 2));
Con cuerdas, necesitarás redondear, pero aún es manejable:
function precise_round(num, decimals) {
var parts = num.split(''.'');
var hasMinus = parts.length > 0 && parts[0].length > 0 && parts[0].charAt(0) == ''-'';
var integralPart = parts.length == 0 ? ''0'' : (hasMinus ? parts[0].substr(1) : parts[0]);
var decimalPart = parts.length > 1 ? parts[1] : '''';
if (decimalPart.length > decimals) {
var roundOffNumber = decimalPart.charAt(decimals);
decimalPart = decimalPart.substr(0, decimals);
if (''56789''.indexOf(roundOffNumber) > -1) {
var numbers = integralPart + decimalPart;
var i = numbers.length;
var trailingZeroes = '''';
var justOneAndTrailingZeroes = true;
do {
i--;
var roundedNumber = ''1234567890''.charAt(parseInt(numbers.charAt(i)));
if (roundedNumber === ''0'') {
trailingZeroes += ''0'';
} else {
numbers = numbers.substr(0, i) + roundedNumber + trailingZeroes;
justOneAndTrailingZeroes = false;
break;
}
} while (i > 0);
if (justOneAndTrailingZeroes) {
numbers = ''1'' + trailingZeroes;
}
integralPart = numbers.substr(0, numbers.length - decimals);
decimalPart = numbers.substr(numbers.length - decimals);
}
} else {
for (var i = decimalPart.length; i < decimals; i++) {
decimalPart += ''0'';
}
}
return (hasMinus ? ''-'' : '''') + integralPart + (decimals > 0 ? ''.'' + decimalPart : '''');
}
alert(precise_round(''1.275'', 2));
alert(precise_round(''1.27499999999999993'', 2));
Tenga en cuenta que esta función redondea al más cercano, se vincula desde cero , mientras que IEEE 754 recomienda redondear al más cercano, incluso como el comportamiento predeterminado para las operaciones de punto flotante. Tales modificaciones se dejan como un ejercicio para el lector :)
Este es un tema antiguo, pero los resultados de Google todavía están mejor clasificados y las soluciones ofrecidas comparten el mismo problema de decimales de punto flotante. Aquí está la función (muy genérica) que uso, gracias a MDN :
function round(value, exp) {
if (typeof exp === ''undefined'' || +exp === 0)
return Math.round(value);
value = +value;
exp = +exp;
if (isNaN(value) || !(typeof exp === ''number'' && exp % 1 === 0))
return NaN;
// Shift
value = value.toString().split(''e'');
value = Math.round(+(value[0] + ''e'' + (value[1] ? (+value[1] + exp) : exp)));
// Shift back
value = value.toString().split(''e'');
return +(value[0] + ''e'' + (value[1] ? (+value[1] - exp) : -exp));
}
Como podemos ver, no tenemos estos problemas:
round(1.275, 2); // Returns 1.28
round(1.27499, 2); // Returns 1.27
Esta genérico también proporciona algunas cosas interesantes:
round(1234.5678, -2); // Returns 1200
round(1.2345678e+2, 2); // Returns 123.46
round("123.45"); // Returns 123
Ahora, para responder a la pregunta del OP, uno tiene que escribir:
round(10.8034, 2).toFixed(2); // Returns "10.80"
round(10.8, 2).toFixed(2); // Returns "10.80"
O, para una función más concisa, menos genérica:
function round2Fixed(value) {
value = +value;
if (isNaN(value))
return NaN;
// Shift
value = value.toString().split(''e'');
value = Math.round(+(value[0] + ''e'' + (value[1] ? (+value[1] + 2) : 2)));
// Shift back
value = value.toString().split(''e'');
return (+(value[0] + ''e'' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
}
Puedes llamarlo con:
round2Fixed(10.8034); // Returns "10.80"
round2Fixed(10.8); // Returns "10.80"
Varios ejemplos y pruebas (gracias a @ tj-crowder !):
function round(value, exp) {
if (typeof exp === ''undefined'' || +exp === 0)
return Math.round(value);
value = +value;
exp = +exp;
if (isNaN(value) || !(typeof exp === ''number'' && exp % 1 === 0))
return NaN;
// Shift
value = value.toString().split(''e'');
value = Math.round(+(value[0] + ''e'' + (value[1] ? (+value[1] + exp) : exp)));
// Shift back
value = value.toString().split(''e'');
return +(value[0] + ''e'' + (value[1] ? (+value[1] - exp) : -exp));
}
function naive(value, exp) {
if (!exp) {
return Math.round(value);
}
var pow = Math.pow(10, exp);
return Math.round(value * pow) / pow;
}
function test(val, places) {
subtest(val, places);
val = typeof val === "string" ? "-" + val : -val;
subtest(val, places);
}
function subtest(val, places) {
var placesOrZero = places || 0;
var naiveResult = naive(val, places);
var roundResult = round(val, places);
if (placesOrZero >= 0) {
naiveResult = naiveResult.toFixed(placesOrZero);
roundResult = roundResult.toFixed(placesOrZero);
} else {
naiveResult = naiveResult.toString();
roundResult = roundResult.toString();
}
$("<tr>")
.append($("<td>").text(JSON.stringify(val)))
.append($("<td>").text(placesOrZero))
.append($("<td>").text(naiveResult))
.append($("<td>").text(roundResult))
.appendTo("#results");
}
test(0.565, 2);
test(0.575, 2);
test(0.585, 2);
test(1.275, 2);
test(1.27499, 2);
test(1234.5678, -2);
test(1.2345678e+2, 2);
test("123.45");
test(10.8034, 2);
test(10.8, 2);
test(1.005, 2);
test(1.0005, 2);
table {
border-collapse: collapse;
}
table, td, th {
border: 1px solid #ddd;
}
td, th {
padding: 4px;
}
th {
font-weight: normal;
font-family: sans-serif;
}
td {
font-family: monospace;
}
<table>
<thead>
<tr>
<th>Input</th>
<th>Places</th>
<th>Naive</th>
<th>Thorough</th>
</tr>
</thead>
<tbody id="results">
</tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Esto es muy simple y funciona tan bien como cualquiera de los otros:
function parseNumber(val, decimalPlaces) {
if (decimalPlaces == null) decimalPlaces = 0
var ret = Number(val).toFixed(decimalPlaces)
return Number(ret)
}
Dado que toFixed () solo puede llamarse en números, y desafortunadamente devuelve una cadena, esto hace todo el análisis por usted en ambas direcciones. Puede pasar una cadena o un número, ¡y obtiene un número cada vez! Llamar a parseNumber (1.49) le dará 1, y parseNumber (1.49,2) le dará 1.50. Al igual que el mejor de ellos!
Estoy arreglando el problema el modificador. Soporta solo 2 decimales.
$(function(){
//input number only.
convertNumberFloatZero(22); // output : 22.00
convertNumberFloatZero(22.5); // output : 22.50
convertNumberFloatZero(22.55); // output : 22.55
convertNumberFloatZero(22.556); // output : 22.56
convertNumberFloatZero(22.555); // output : 22.55
convertNumberFloatZero(22.5541); // output : 22.54
convertNumberFloatZero(22222.5541); // output : 22,222.54
function convertNumberFloatZero(number){
if(!$.isNumeric(number)){
return ''NaN'';
}
var numberFloat = number.toFixed(3);
var splitNumber = numberFloat.split(".");
var cNumberFloat = number.toFixed(2);
var cNsplitNumber = cNumberFloat.split(".");
var lastChar = splitNumber[1].substr(splitNumber[1].length - 1);
if(lastChar > 0 && lastChar < 5){
cNsplitNumber[1]--;
}
return Number(splitNumber[0]).toLocaleString(''en'').concat(''.'').concat(cNsplitNumber[1]);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
No encontré una solución precisa para este problema, así que creé la mía:
function inprecise_round(value, decPlaces) {
return Math.round(value*Math.pow(10,decPlaces))/Math.pow(10,decPlaces);
}
function precise_round(value, decPlaces){
var val = value * Math.pow(10, decPlaces);
var fraction = (Math.round((val-parseInt(val))*10)/10);
//this line is for consistency with .NET Decimal.Round behavior
// -342.055 => -342.06
if(fraction == -0.5) fraction = -0.6;
val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
return val;
}
Ejemplos:
function inprecise_round(value, decPlaces) {
return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
function precise_round(value, decPlaces) {
var val = value * Math.pow(10, decPlaces);
var fraction = (Math.round((val - parseInt(val)) * 10) / 10);
//this line is for consistency with .NET Decimal.Round behavior
// -342.055 => -342.06
if (fraction == -0.5) fraction = -0.6;
val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
return val;
}
// This may produce different results depending on the browser environment
console.log("342.055.toFixed(2) :", 342.055.toFixed(2)); // 342.06 on Chrome & IE10
console.log("inprecise_round(342.055, 2):", inprecise_round(342.055, 2)); // 342.05
console.log("precise_round(342.055, 2) :", precise_round(342.055, 2)); // 342.06
console.log("precise_round(-342.055, 2) :", precise_round(-342.055, 2)); // -342.06
console.log("inprecise_round(0.565, 2) :", inprecise_round(0.565, 2)); // 0.56
console.log("precise_round(0.565, 2) :", precise_round(0.565, 2)); // 0.57
No sé por qué no puedo agregar un comentario a una respuesta anterior (tal vez estoy totalmente ciego, no sé), pero se me ocurrió una solución utilizando la respuesta de @Miguel:
function precise_round(num,decimals) {
return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
}
Y sus dos comentarios (de @bighostkim y @Imre):
- Problema con
precise_round(1.275,2)
no devuelve 1.28 - Problema con
precise_round(6,2)
no devuelve 6.00 (como él quería).
Mi solución final es la siguiente:
function precise_round(num,decimals) {
var sign = num >= 0 ? 1 : -1;
return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
}
Como puede ver, tuve que agregar un poco de "corrección" (no es lo que es, pero dado que Math.round tiene pérdidas, puede verlo en jsfiddle.net, esta es la única forma en que supe cómo "corregir" " eso). Agrega 0.001 al número ya rellenado, por lo que está agregando 1
tres 0
s a la derecha del valor decimal. Por lo tanto, debe ser seguro de usar.
Después de eso agregué .toFixed(decimal)
para generar siempre el número en el formato correcto (con la cantidad correcta de decimales).
Así que eso es todo. Úsalo bien ;)
EDITAR: funcionalidad agregada a la "corrección" de números negativos.
Para formatear un número usando la notación de punto fijo, simplemente puede usar el método toFixed :
(10.8).toFixed(2); // "10.80"
var num = 2.4;
alert(num.toFixed(2)); // "2.40"
Tenga en cuenta que toFixed()
devuelve una cadena.
IMPORTANTE : Tenga en cuenta que el hecho de Fijar no redondea realmente, el 90% del tiempo, devolverá el valor redondeado, pero en muchos casos no funciona. Prueba esto en tu consola:
2.005.toFixed(2)
Obtendrás la respuesta incorrecta
No hay una forma natural de obtener un redondeo decimal en javascript, necesitará su propio polyfill o use una biblioteca. Puede consultar el polyfill de mozilla para este https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
Ponga lo siguiente en un alcance global:
Number.prototype.getDecimals = function ( decDigCount ) {
return this.toFixed(decDigCount);
}
y luego intente :
var a = 56.23232323;
a.getDecimals(2); // will return 56.23
Actualizar
Tenga en cuenta que toFixed()
solo puede funcionar para el número de decimales entre 0-20
es decir, a.getDecimals(25)
puede generar un error de javascript, por lo que puede agregar un cheque adicional.
Number.prototype.getDecimals = function ( decDigCount ) {
return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
}
Por lo general, agrego esto a mi biblioteca personal, y luego de algunas sugerencias y uso de la solución @TIMINeutron también, y haciéndolo adaptable para la longitud decimal, esta se ajusta mejor:
function precise_round(num, decimals) {
var t = Math.pow(10, decimals);
return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}
Trabajará para las excepciones reportadas.
Recibí algunas ideas de esta publicación hace unos meses, pero ninguna de las respuestas aquí, ni las respuestas de otras publicaciones / blogs pudieron manejar todos los escenarios (p. Ej., Números negativos y algunos "números de la suerte", según nuestro comprobador). Al final, nuestro probador no encontró ningún problema con este método a continuación. Pegando un fragmento de mi código:
fixPrecision: function (value) {
var me = this,
nan = isNaN(value),
precision = me.decimalPrecision;
if (nan || !value) {
return nan ? '''' : value;
} else if (!me.allowDecimals || precision <= 0) {
precision = 0;
}
//[1]
//return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
precision = precision || 0;
var negMultiplier = value < 0 ? -1 : 1;
//[2]
var numWithExp = parseFloat(value + "e" + precision);
var roundedNum = parseFloat(Math.round(Math.abs(numWithExp)) + ''e-'' + precision) * negMultiplier;
return parseFloat(roundedNum.toFixed(precision));
},
También tengo comentarios de código (perdón, ya olvidé todos los detalles) ... Estoy publicando mi respuesta aquí para futuras referencias:
9.995 * 100 = 999.4999999999999
Whereas 9.995e2 = 999.5
This discrepancy causes Math.round(9.995 * 100) = 999 instead of 1000.
Use e notation instead of multiplying /dividing by Math.Pow(10,precision).
Redondea tu valor decimal, luego usa toFixed(x)
para tus dígitos esperados.
function parseDecimalRoundAndFixed(num,dec){
var d = Math.pow(10,dec);
return (Math.round(num * d) / d).toFixed(dec);
}
Llamada
parseDecimalRoundAndFixed (10.800243929,4) => 10.80 parseDecimalRoundAndFixed (10.807243929,2) => 10.81
También puede usar el método .toPrecision()
y algunos códigos personalizados, y siempre redondear hasta el décimo dígito decimal, independientemente de la longitud de la parte int.
function glbfrmt (number, decimals, seperator) {
return typeof number !== ''number'' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals);
}
También puede hacer que sea un complemento para un mejor uso.
Tan simple como esto.
var rounded_value=Math.round(value * 100) / 100;
Una forma de estar 100% seguro de obtener un número con 2 decimales:
(Math.round(num*100)/100).toFixed(2)
Si esto causa errores de redondeo, puede usar lo siguiente como James ha explicado en su comentario:
(Math.round((num * 1000)/10)/100).toFixed(2)
Usando esta respuesta por referencia: https://.com/a/21029698/454827
Construyo una función para obtener números dinámicos de decimales:
function toDec(num, dec)
{
if(typeof dec==''undefined'' || dec<0)
dec = 2;
var tmp = dec + 1;
for(var i=1; i<=tmp; i++)
num = num * 10;
num = num / 10;
num = Math.round(num);
for(var i=1; i<=dec; i++)
num = num / 10;
num = num.toFixed(dec);
return num;
}
aquí trabajando ejemplo: https://jsfiddle.net/wpxLduLc/
Redondear a la baja
function round_down(value, decPlaces) {
return Math.floor(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
Redondeo
function round_up(value, decPlaces) {
return Math.ceil(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
Redondeo más cercano
function round_nearest(value, decPlaces) {
return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
Fusionado https://.com/a/7641824/1889449 y https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm Gracias.
/**
* MidpointRounding away from zero (''arithmetic'' rounding)
* Uses a half-epsilon for correction. (This offsets IEEE-754
* half-to-even rounding that was applied at the edge cases).
*/
function RoundCorrect(num, precision = 2) {
// half epsilon to correct edge cases.
var c = 0.5 * Number.EPSILON * num;
// var p = Math.pow(10, precision); //slow
var p = 1; while (precision--> 0) p *= 10;
if (num < 0)
p *= -1;
return Math.round((num + c) * p) / p;
}
// testing some +ve edge cases
console.log(RoundCorrect(1.005, 2)); // 1.01 correct
console.log(RoundCorrect(2.175, 2)); // 2.18 correct
console.log(RoundCorrect(5.015, 2)); // 5.02 correct
// testing some -ve edge cases
console.log(RoundCorrect(-1.005, 2)); // -1.01 correct
console.log(RoundCorrect(-2.175, 2)); // -2.18 correct
console.log(RoundCorrect(-5.015, 2)); // -5.02 correct
parse = function (data) {
data = Math.round(data*Math.pow(10,2))/Math.pow(10,2);
if (data != null) {
var lastone = data.toString().split('''').pop();
if (lastone != ''.'') {
data = parseFloat(data);
}
}
return data;
};
$(''#result'').html(parse(200)); // output 200
$(''#result1'').html(parse(200.1)); // output 200.1
$(''#result2'').html(parse(200.10)); // output 200.1
$(''#result3'').html(parse(200.109)); // output 200.11
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="result"></div>
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
/*Due to all told stuff. You may do 2 things for different purposes:
When showing/printing stuff use this in your alert/innerHtml= contents:
YourRebelNumber.toFixed(2)*/
var aNumber=9242.16;
var YourRebelNumber=aNumber-9000;
alert(YourRebelNumber);
alert(YourRebelNumber.toFixed(2));
/*and when comparing use:
Number(YourRebelNumber.toFixed(2))*/
if(YourRebelNumber==242.16)alert("Not Rounded");
if(Number(YourRebelNumber.toFixed(2))==242.16)alert("Rounded");
/*Number will behave as you want in that moment. After that, it''ll return to its defiance.
*/
(Math.round((10.2)*100)/100).toFixed(2)
Eso debería rendir: 10.20
(Math.round((.05)*100)/100).toFixed(2)
Eso debería rendir: 0.05
(Math.round((4.04)*100)/100).toFixed(2)
Eso debería rendir: 4.04
etc.
Number(((Math.random() * 100) + 1).toFixed(2))
esto devolverá un número aleatorio de 1 a 100 redondeado a 2 decimales.
Number(Math.round(1.005+''e2'')+''e-2''); // 1.01
Esto funcionó para mí: Redondeando decimales en JavaScript