14

All I can think of is to repeatedly divide the number by 10 (until number is less than 10) and keep a count, but is there a trick for this sort of thing?

General Grievance
  • 4,555
  • 31
  • 31
  • 45
ronT
  • 141
  • 1
  • 1
  • 3

11 Answers11

17

Yep, you pretty much have the mathematical way to do it right there.

while (num >= 10)
    digit = num MOD 10   // and save this into an array or whatever
    num = num / 10

at the end of this, num will contain the last digit.

Here's a Javascript implementation:

function getDigits(num) {
    var digits = [];
    while (num >= 10) {
        digits.unshift(num % 10);
        num = Math.floor(num / 10);
    }
    digits.unshift(num);
    return digits;
}

Note that it only works for non-negative integers.

nickf
  • 537,072
  • 198
  • 649
  • 721
9

Why implement the conversion yourself when there's already a very reliable way to do it?

In pseudo-C:

char digits[10];
sprintf(digits, "%d", number);

Now your digits char array (string) should consist of each digit of the number. Most other scripting languages also contain a sprintf function.

This will work if you want base 8 or base 16 or binary, etc. Just use a different format specifier.

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
tchen
  • 2,212
  • 1
  • 16
  • 18
  • but not generalizable to bases other than 16, 10, or 8. (binary doesn't have a "%" specifier for the standard version of sprintf) – Jason S Sep 01 '10 at 00:25
  • Then, if you want to use them as actual digits, you have to subtract `'0'` from all of them. As for why... maybe you're doing some recreational computational math problems and you don't want that bit of extra overhead. I'm sure there are project euler problems using the digits of a number! – Cascabel Sep 01 '10 at 00:32
  • I hate this converting to strings. I will downwote this as soon as I can. I just think it is really bad solution. – Bart Sep 02 '10 at 07:00
  • As I said -1. I the number is too long it will override mem after 9 digits (one byte for null char). And what if for some reason wide char strings will be used ? `number` is a number so there are functions `div` and `mod` for that purpose. – Bart Sep 02 '10 at 11:29
  • 1
    A 32 bit integer will not have more than 9 digits (in base 10 at least). Adjust this if you want to handle 64-bit integers. And as for using div and mod, that's what sprintf() would use internally. The OP only wanted to extract the digits, he did not state for what purpose. If it is for computational purposes, then I can imagine a different method may be more appropriate, this is just one method. – tchen Sep 09 '10 at 23:03
4

The mathematical answer is to mod by 10 and add each result to a list, then reverse the list's order. Here's a basic C# algorithm that will do this:

List<byte> digits = new List<byte>();

while(number > 10)
{
   digits.Add(number % 10);
   number %= 10;
}
//add the last digit
digits.Add(number);

byte temp;
for(var i=0;i<digits.Count/2;i++)
{
   temp = digits[i];
   digits[i] = digits[digits.Count-(i+1)];
   digits[digits.Count-(i+1)] = temp;
}

Other "tricks" usually involve a string conversion. Here's a C# one-liner using Linq that will give the same result as the above:

var digits = number.ToString().Select(c=>byte.Parse(c)).ToList();
smac89
  • 39,374
  • 15
  • 132
  • 179
KeithS
  • 70,210
  • 21
  • 112
  • 164
3

Python code using your approach:

def digits(n):
  ds = []
  while n > 0:
    ds.append(n % 10)
    n /= 10
  ds.reverse()
  return ds

Using convertation to string:

def digits(n):           
  return map(int, str(n))
smac89
  • 39,374
  • 15
  • 132
  • 179
Vadim Shender
  • 6,703
  • 1
  • 16
  • 10
1

If it is an Integer, you could convert the string representation into an array of characters, and then convert that into an array of bytes (0-9)

Charles Bretana
  • 143,358
  • 22
  • 150
  • 216
  • I think converting it into a string representation would essentially do repeatedly dividing by 10. At least, that's how I would be doing it. – David Liu Sep 01 '10 at 01:06
  • What if it's in hex? – munmunbb Feb 12 '17 at 05:15
  • An integer is an integer, it's stored in memory the same way regardless of whether you see it displayed in decimal, hex, binary or whatever. Are you asking how to extract the individual characters in the hex *representation*? If so, just get the hex representation as a string, and then take the characters in that string. – Charles Bretana Feb 12 '17 at 05:33
1

A more efficient algorithm, if your input numbers may be large, is to divide by a power of 10, say 1000, and use a lookup table:

s = ""; // or use a string builder appropriate to your language...
table = {"000", "001", ..., "999"};
tableInitial = {"unused", "1", "2", ..., "9", "10", ..., "999"};
while(n >= 1000) {
  m = n%1000;
  n /= 1000;
  s = table[m] + s;
}
s = tableInitial[n] + s;
Charles
  • 11,269
  • 13
  • 67
  • 105
  • modding is effectively a log(n) operation for any number N. It doesn't get a whole lot more efficient even for large numbers. – KeithS Feb 02 '12 at 17:23
  • 1
    @KeithS: Asymptotically, binary splitting--reducing the number mod 10^k with k about log_100 N for an input N--gives a speedup as long as you're using fast division (FFT or even Karatsuba). Practically speaking, reducing mod the smallest power of ten less than the square root of the largest integer that fits in a word is just as fast as reducing mod 10, so you get almost a 9x speedup on large numbers on a 64-bit machine. You can combine the two approaches by moving from the asymptotic method to the practical once you hit some threshold. In my experience it's about 1000 digits, but it varies. – Charles Feb 02 '12 at 17:56
0

Not sure if I understood what you want correctly...

Would the below work for you?? It is written in C#...

public static List<int> ExtractDigit()
{
    // Input example
    int number = 12345;

    // Convert Integer to string   
    string numberedString = number.ToString();

    // Create a list of integers
    var numList = new List<int>();

    // Convert each character in string back to int and add to list.
    foreach (char c in numberedString)
    {
        numList.Add(Convert.ToInt32(c.ToString()));
    }

    return numList;
}

I hope i was of help.

smac89
  • 39,374
  • 15
  • 132
  • 179
DottoreM
  • 309
  • 6
  • 27
0

Following program would work as well.

public class Main {
    public static void main(String[] args) {
        int i1 =123456;
        String s =new StringBuilder(String.valueOf(i1)).toString();
        char a[]=s.toCharArray();
        for(char c : a) {
            Integer i = Integer.parseInt(c+"");
            System.out.println(i);
        }
    }
}
Shailesh Pratapwar
  • 4,054
  • 3
  • 35
  • 46
0

The given python solution could be further optimized using

zerostr = ord('0')
def digits(n): 
    return map(lambda x: ord(x)-zerostr, str(n))

In fact, where the int -> str conversion is probably completely optimized, to get the numeric value it's much better to use the instrinsic character value of the digit string, which in every encoding (including EBCDIC) gives the numeric value by means of an int subtraction instead of a str parsing.

smac89
  • 39,374
  • 15
  • 132
  • 179
rewritten
  • 16,280
  • 2
  • 47
  • 50
0

JavaScript:

function digits(num) {
  return String(num).split('').map(v => +v);
}
AJ Meyghani
  • 4,389
  • 1
  • 31
  • 35
0

Here are reversible array functions in JavaScript that handle integers or strings:

function reverse(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0, right = length - 1; left < right; left += 1, right -= 1)
    {
        var temporary = array[left];
        array[left] = array[right];
        array[right] = temporary;
    }
    return array;
}

function toDigitsArrayFromInteger(integer, isReverse)
{
    var digits = [];

    if (integer > 0)
    {
        var floor = window.Math.floor;
        while (integer > 0)
        {
            digits.push(floor(integer % 10));
            integer = floor(integer / 10);
        }

        // Array is populated in reverse order. Un-reverse it to make it normal.
        if (!isReverse)
        {
            digits = reverse(digits);
        }
    }
    else if (integer < 0)
    {
        digits = toDigitsArrayFromInteger(-integer, isReverse);
    }
    else if (integer === 0)
    {
        digits.push(0);
    }

    return digits;
}

function toDigitsArrayFromString(string, isReverse)
{
    var digits = [];

    string += ""; // Coerce to string.

    var i = null;
    var length = string.length;
    for (i = 0; i < length; i += 1)
    {
        var integer = parseInt(string.charAt(i), 10);
        if (isFinite(integer))
        {
            digits.push(integer);
        }
    }

    if (isReverse)
    {
        digits = reverse(digits);
    }

    return digits;
}

Once you have the digits as an array, you can reverse the array easily to get the digits starting from the left or from the right.

The string function is more versatile because it can find any digit in a string, whereas the integer function is limited to integers.

Benchmarks: http://jsperf.com/todigitsarray

The benchmarks between the two functions show that in Firefox 10 and Chrome 12, the string function is 30% to 60% faster than the integer function. In Opera 12, the integer function is slightly faster by about 10%.

smac89
  • 39,374
  • 15
  • 132
  • 179
XP1
  • 6,910
  • 8
  • 54
  • 61