solo - quitar decimales sin redondear javascript
Truncar(no redondear) nĂºmeros decimales en javascript (22)
Estoy tratando de truncar números decimales a decimales. Algo como esto:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
hace lo correcto pero redondea el valor. No necesito el valor redondeado. Espero que esto sea posible en javascript.
Aquí hay un código ES6 que hace lo que quieres
const truncateTo = (unRouned, nrOfDecimals = 2) => {
const parts = String(unRouned).split(".");
if (parts.length !== 2) {
// without any decimal part
return unRouned;
}
const newDecimals = parts[1].slice(0, nrOfDecimals),
newString = `${parts[0]}.${newDecimals}`;
return Number(newString);
};
// your examples
console.log(truncateTo(5.467)); // ---> 5.46
console.log(truncateTo(985.943)); // ---> 985.94
// other examples
console.log(truncateTo(5)); // ---> 5
console.log(truncateTo(-5)); // ---> -5
console.log(truncateTo(-985.943)); // ---> -985.94
Aquí hay una función simple pero funcional para truncar el número hasta 2 decimales.
function truncateNumber(num) {
var num1 = "";
var num2 = "";
var num1 = num.split(''.'')[0];
num2 = num.split(''.'')[1];
var decimalNum = num2.substring(0, 2);
var strNum = num1 +"."+ decimalNum;
var finalNum = parseFloat(strNum);
return finalNum;
}
Aquí mi opinión sobre el tema:
convert.truncate = function(value, decimals) {
decimals = (decimals === undefined ? 0 : decimals);
return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10);
};
Es solo una versión un poco más elaborada de
(f - 0.005).toFixed(2)
Buena solución de una sola línea:
function truncate (num, places) {
return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}
Luego llámalo con:
truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632
Considera tomar ventaja de la doble tilde: ~~
.
Toma el número. Multiplique por dígitos significativos después del decimal para que pueda truncate a cero lugares con ~~
. Divida ese multiplicador de nuevo. Lucro.
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
Estoy tratando de resistir el envolver la ~~
llamada en parens; orden de las operaciones debería hacer que funcione correctamente, creo.
alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
EDITAR: Mirando hacia atrás, sin querer también he manejado casos para redondear a la izquierda del decimal también.
alert(truncator(4343.123, -2)); // gives 4300.
La lógica es un poco raro buscando ese uso, y puede beneficiarse de un refactor rápido. Pero todavía funciona. Mejor suerte que bien.
Creo que esta función podría ser una solución simple:
function trunc(decimal,n=2){
let x = decimal + ''''; // string
return x.lastIndexOf(''.'')>=0?parseFloat(x.substr(0,x.lastIndexOf(''.'')+(n+1))):decimal; // You can use indexOf() instead of lastIndexOf()
}
console.log(trunc(-241.31234,2));
console.log(trunc(241.312,5));
console.log(trunc(-241.233));
console.log(trunc(241));
El que está marcado como la solución es la mejor solución que he encontrado hasta hoy, pero tiene un serio problema con 0 (por ejemplo, 0.toFixedDown (2) da -0.01). Entonces sugiero usar esto:
Number.prototype.toFixedDown = function(digits) {
if(this == 0) {
return 0;
}
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);
}
El tipo resultante sigue siendo un número ...
/* Return the truncation of n wrt base */
var trunc = function(n, base) {
n = (n / base) | 0;
return base * n;
};
var t = trunc(5.467, 0.01);
Encontré un problema: considerando la siguiente situación: 2.1 o 1.2 o -6.4
¿Qué pasa si quieres siempre 3 decimales o dos o más? Entonces, debes completar los ceros a la derecha
// 3 decimals numbers
0.5 => 0.500
// 6 decimals
0.1 => 0.10000
// 4 decimales
-2.1 => -2.1000
// truncate to 3 decimals
3.11568 => 3.115
Esta es la función fija de Nick Knowlson
function truncateDecimals (num, digits)
{
var numS = num.toString();
var decPos = numS.indexOf(''.'');
var substrLength = decPos == -1 ? numS.length : 1 + decPos + digits;
var trimmedResult = numS.substr(0, substrLength);
var finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
// adds leading zeros to the right
if (decPos != -1){
var s = trimmedResult+"";
decPos = s.indexOf(''.'');
var decLength = s.length - decPos;
while (decLength <= digits){
s = s + "0";
decPos = s.indexOf(''.'');
decLength = s.length - decPos;
substrLength = decPos == -1 ? s.length : 1 + decPos + digits;
};
finalResult = s;
}
return finalResult;
};
Esto es lo que uso:
var t = 1;
for (var i = 0; i < decimalPrecision; i++)
t = t * 10;
var f = parseFloat(value);
return (Math.floor(f * t)) / t;
La respuesta de @ Dogbert se puede mejorar con Math.trunc
, que trunca en lugar de redondear.
Hay una diferencia entre redondear y truncar. Truncar es claramente el comportamiento que busca esta pregunta. Si llamo truncado (-3.14) y recibo -4 de regreso, definitivamente lo llamaría indeseable. - @NickKnowlson
var a = 5.467;
var truncated = Math.trunc(a * 100) / 100; // = 5.46
var a = -5.467;
var truncated = Math.trunc(a * 100) / 100; // = -5.46
La respuesta de @kirilloid parece ser la respuesta correcta, sin embargo, el código principal debe actualizarse. Su solución no se ocupa de los números negativos (que alguien mencionó en la sección de comentarios pero no se ha actualizado en el código principal).
Actualizando eso a una solución completa final probada:
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();
};
Uso de la muestra:
var x = 3.1415629;
Logger.log(x.toFixedDown(2)); //or use whatever you use to log
Violín: Número JS Redondea hacia abajo
PD: No hay suficiente repo para comentar sobre esa 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í mismo puede dar resultados inesperados.
Ej. Math.floor(4.3) = 4
, pero Math.floor(-4.3) = -5
Use una función de ayuda 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 correctamente señala que usar esta solución con a = 17.56
producirá incorrectamente 17.55
. Para obtener más información acerca de por qué ocurre esto, lea Lo que todo científico informático debería saber sobre la aritmética de coma flotante . Desafortunadamente, escribir una solución que elimine todas las fuentes de error de coma flotante es bastante complicado con javascript. En otro idioma, usaría enteros o tal vez un tipo Decimal, pero con javascript ...
Esta solución debe ser 100% precisa, pero también será más lenta:
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 los errores de coma flotante, pruebe algo como BigDecimal.js . Puede encontrar otras bibliotecas BigDecimal de JavaScript en esta pregunta SO: "¿Hay una buena biblioteca BigDecimal de JavaScript?" y aquí hay una buena publicación en el blog sobre bibliotecas matemáticas para Javascript
Pensé que lanzaría una respuesta usando |
ya que es simple y funciona bien.
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
Puede corregir el redondeo restando 0.5 a Fijo, por ejemplo
(f - 0.005).toFixed(2)
Truncar usando operadores bit a bit:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
solo para señalar una solución simple que funcionó para mí
conviértalo en una cadena y luego regexalo ...
var number = 123.45678;
var number_s = '''' + number;
var number_truncated_s = number_s.match(//d*/./d{4}/)[0]
var number_truncated = parseFloat(number_truncated_s)
Se puede abreviar a
var number_truncated = parseFloat(('''' + 123.4568908).match(//d*/./d{4}/)[0])
upd :
Entonces, después de todo resultó que, los errores de redondeo siempre te perseguirán, sin importar cuánto intentes compensarlos. Por lo tanto, el problema debe atacarse representando 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]
Antigua solución propensa a errores basada en la compilación de los demás:
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);
}
Number.prototype.trim = function(decimals) {
var s = this.toString();
var d = s.split(".");
d[1] = d[1].substring(0, decimals);
return parseFloat(d.join("."));
}
console.log((5.676).trim(2)); //logs 5.67
Number.prototype.truncate = function(places) {
var shift = Math.pow(10, places);
return Math.trunc(this * shift) / shift;
};
function toFixed(number, digits) {
var reg_ex = new RegExp("(//d+//.//d{" + digits + "})(//d)")
var array = number.toString().match(reg_ex);
return array ? parseFloat(array[1]) : number.valueOf()
}
var test = 10.123456789
var __fixed = toFixed(test, 6)
console.log(__fixed)
// => 10.123456
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46