I just wanted to add a few details on the definition of the problem and the solutions of the other answers. It’s not that they’re wrong, but there’s a few you pay attention to.
First, if the numbers are, for example, 1.5
, 1.05
and 1.00005
: for these three cases, it is said that the decimal part is 5
. Behold:
function splitNumber(num) {
const [int = 0, decimal = 0] = num.toString()
.split('.')
.map((num) => parseInt(num));
return [int, decimal];
}
console.log(splitNumber(1.5)); // [1, 5]
console.log(splitNumber(1.05)); // [1, 5]
console.log(splitNumber(1.00005)); // [1, 5]
But actually the decimal part of the second and third numbers is not exactly 5
. In a is 0.05
and the other is 0.00005
- these zeroes make all the difference, because it’s not the same value.
So here comes the other one that I mentioned, which is the definition of the problem: it makes no sense to turn the decimal part into an integer, because for integers the left zero makes no difference, but for decimal places it does. Therefore, I suggest you do not make this transformation, and keep the decimal part as it is, without converting to integer. So you don’t lose the decimals.
Another problem is that turning the number into a string will not always work as expected:
function splitNumber(num) {
const [int = 0, decimal = 0] = num.toString()
.split('.')
.map((num) => parseInt(num));
return [int, decimal];
}
console.log(splitNumber(0.0000005)); // [5, 0]
console.log(splitNumber(10000000000000000000000)); // [1, 0]
console.log(splitNumber(10000000000000000000000.99299284982)); // [1, 0]
This is because from a certain value "very large" (or "very small"), the method toString
returns the number represented in scientific notation. In the case of 0.0000005
, for example, the result of toString
is 5e-7
. And how the function does the split
of this string using the point as separator, the result turns out not to be the expected (related question).
One way to avoid this problem (and also the first, of not preserving all zeros of the decimal places) is simply to truncate the number to get the whole part, and then subtract this whole part from the original number (so what remains is the decimal part):
function splitNumber(num) {
const int = Math.trunc(num);
return [int, num - int];
}
console.log(splitNumber(1.5));
console.log(splitNumber(1.05));
console.log(splitNumber(1.00005));
console.log(splitNumber(0.0000005));
console.log(splitNumber(10000000000000000000000));
console.log(splitNumber(10000000000000000000000.99299284982));
But of course we now generate other "problems". In the second number above, the decimal part is 0.05
, but the result turned out to be 0.050000000000000044
. This happens because of how floating point numbers work. There is a more detailed explanation here, and in this answer has several other links that you can follow to delve into the subject. But at least we don’t remove the zeroes from the decimals, which in my opinion is an improvement.
And in the last number, the resulting decimal part was zero, as the decimal places were ignored because thereof. That is, even using math instead of conversion to strings, we will still be limited to the language’s implementation features (and there’s no way around that much - unless you use dedicated libraries to handle values as large as that one).
It is worth remembering that the solution with toString
is also subject to this behavior, since it is something intrinsic to the way floating point numbers work:
function splitNumber(num) {
const [int = 0, decimal = 0] = num.toString()
.split('.')
.map((num) => parseInt(num));
return [int, decimal];
}
var x = 1.05 - 1; // supondo que o número é resultado de algum cálculo
console.log(splitNumber(x)); // [0, 50000000000000050]
If you want to avoid this, then you would have to deal with the numbers before (or after), either by rounding up, eliminating decimal places, etc (but then I believe you already escape the scope of the question).
What have you ever tried to do?
– DaviAragao