Es importante tener en cuenta que no estoy buscando una función de redondeo. Estoy buscando una función que devuelva el número de decimales en la representación decimal simplificada de un número arbitrario. Es decir, tenemos los siguientes:¿Existe alguna forma confiable en JavaScript para obtener el número de decimales de un número arbitrario?
decimalPlaces(5555.0); //=> 0
decimalPlaces(5555); //=> 0
decimalPlaces(555.5); //=> 1
decimalPlaces(555.50); //=> 1
decimalPlaces(0.0000005); //=> 7
decimalPlaces(5e-7); //=> 7
decimalPlaces(0.00000055); //=> 8
decimalPlaces(5.5e-7); //=> 8
Mi primer instinto era utilizar las representaciones de cadena: división en '.'
, a continuación, en 'e-'
, y hacer los cálculos, al igual que (el ejemplo es detallado):
function decimalPlaces(number) {
var parts = number.toString().split('.', 2),
integerPart = parts[0],
decimalPart = parts[1],
exponentPart;
if (integerPart.charAt(0) === '-') {
integerPart = integerPart.substring(1);
}
if (decimalPart !== undefined) {
parts = decimalPart.split('e-', 2);
decimalPart = parts[0];
}
else {
parts = integerPart.split('e-', 2);
integerPart = parts[0];
}
exponentPart = parts[1];
if (exponentPart !== undefined) {
return integerPart.length +
(decimalPart !== undefined ? decimalPart.length : 0) - 1 +
parseInt(exponentPart);
}
else {
return decimalPart !== undefined ? decimalPart.length : 0;
}
}
Para mis ejemplos anteriores, esta función funciona. Sin embargo, no estoy satisfecho hasta que haya probado todos los valores posibles, así que eliminé Number.MIN_VALUE
.
Number.MIN_VALUE; //=> 5e-324
decimalPlaces(Number.MIN_VALUE); //=> 324
Number.MIN_VALUE * 100; //=> 4.94e-322
decimalPlaces(Number.MIN_VALUE * 100); //=> 324
Esto parecía razonable al principio, pero luego en una toma doble me di cuenta de que debería haber 5e-324 * 10
5e-323
! Y luego me di cuenta: estoy lidiando con los efectos de la cuantificación de números muy pequeños. No solo se cuantifican los números antes del almacenamiento; adicionalmente, algunos números almacenados en binario tienen representaciones decimales irracionalmente largas, por lo que sus representaciones decimales se están truncando. Esto es desafortunado para mí, porque significa que no puedo obtener su precisión decimal real usando sus representaciones de cadena.
Así que vengo a ti, comunidad de StackOverflow. ¿Alguien entre ustedes conoce una manera confiable de llegar a la precisión de un punto verdadero después del punto decimal?
El propósito de esta función, si alguien pregunta, es para usar en otra función que convierta un flotador en una fracción simplificada (es decir, devuelve el numerador entero relativamente coprimario y el denominador natural distinto de cero). La única pieza que falta en esta función externa es una manera confiable de determinar el número de lugares decimales en el flotador para poder multiplicarlo por la potencia apropiada de 10. Afortunadamente estoy pensando demasiado.
Hay un número infinito de lugares decimales en cualquier número de coma flotante. –
Puede estar interesado en esto: http://blog.thatscaptaintoyou.com/introducing-big-js-arbitrary-precision-math-for-javascript/ –
@LightnessRacesinOrbit: bien, bueno, no pude incluir todos los detalles en ¡el título! Sí especifico en la pregunta, sin embargo, que estoy buscando la representación simplificada. – Milosz