2

I was working on a Javascript exercise that required a number to be converted into an array of single digits and the only way I can seem to achieve this is by converting the number into a string and then converting it back to a number.

let numbers = 12345;

Array.from(numbers.toString(10), Number) // [1, 2, 3, 4, 5]

Basically, I'm wondering if this is the best way to achieve a split like this on a number or if there is a more efficient method that doesn't require such a conversion.

  • Not a duplicate, but a parallel, is bit masking. https://stackoverflow.com/questions/10493411/what-is-bit-masking You can see about using a similar idea for decimal, hex, or whatever numerical system you want to use. And yes, masking can be done in other systems than binary. – computercarguy Jul 22 '19 at 23:58

2 Answers2

1

You can always get the smallest digit with n % 10. You can remove this digit with subtraction and division by 10 (or divide and floor). This makes for a pretty simple loop:

function digits(numbers){
  if (numbers == 0) return [numbers]
  let res = []
  while (numbers){
    let n = numbers % 10
    res.push(n)
    numbers = (numbers - n) / 10
  }
  return res.reverse()
}

console.log(digits(1279020))

This takes the numbers in reverse order so you either have to unshift the results on to the array or push and reverse at the end.

One of the nice things about this, is that you can find the digits of different bases by swapping out 10 for a the base of your choice:

function digits(numbers, base){
  if (numbers == 0) return [numbers]
  let res = []
  while (numbers){
    let n = numbers % base
    res.push(n)
    numbers = (numbers - n) / base
  }
  return res.reverse()
}
// binary
console.log(digits(20509, 2).join(''))
console.log((20509).toString(2))

// octal
console.log(digits(20509, 8).join(''))
console.log((20509).toString(8))

Although once your base is larger than 10 you will have to map those digits to the appropriate letters.

Mark
  • 90,562
  • 7
  • 108
  • 148
0

One approach would be to iterate through the number of digits and calculate the difference of each modulo by base, and then populate the output list from the result of each iteration.

A quick way to identify the number of digits in your base 10 input would be the following:

Math.floor(Math.log(input) / Math.LN10 + 1) // 5 for input of 12349

Next, iterate through this range and for each iteration, calculate the base of the current and previous iterations, and perform module of the input against these. The digit for the current iteration is then derived from the difference of the modulo calculations like this:

function arrayFromInput(input) {

  const output = [];

  for (let i = 0; i < Math.floor(Math.log(input) / Math.LN10 + 1); i++) {

    const lastBase = Math.pow(10, i);
    const nextBase = Math.pow(10, i + 1);

    const lastMod = input % lastBase;
    const nextMod = input % nextBase;

    const digit = (nextMod - lastMod) / lastBase;

    output.unshift(digit);

  }
  
  return output;

}

console.log(arrayFromInput(12345), '= [1,2,3,4,5]');
console.log(arrayFromInput(12), '= [1,2]');
console.log(arrayFromInput(120), '= [1,2 0]');
console.log(arrayFromInput(9), '= [9]');
console.log(arrayFromInput(100), '= [1,0,0]');
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65