Counting the Digits

I am not a math genius, as any math genius who reviews my work is happy to tell me. Even so, when programming I’m often faced with math challenges where a math education would benefit. My most recent puzzle is how to count the number of digits in a value without first converting the value into a string.

If you visit this blog regularly, yes, this Lesson hints at an upcoming Exercise challenge. Still, the problem intrigued me: Does some mathematical trick exist that determines how a value such as 12345 contains five digits? Rather than research such a solution, I just started to code. Typical.

Given the Power of the Computer, I devised a brute-force method to determine the number of digits in a value by subtracting successive powers of 10 from a given number. To ensure that large values are properly processed, I use long integer types in the following code:

2022_08_20-Lesson-a.c

#include <stdio.h>

int main()
{
    long d;
    int x,l;
    long value[10] = {
        1, 12, 123, 1234, 12345,
        123456, 1234567, 12345678,
        123456789, 1234567890
    };

    for( x=0; x<10; x++ )
    {
        l=d=1;
        while( d<=10000000000 )
        {
            if( value[x]<d )
            {
                printf("%ld is %d digits long\n",value[x],l-1);
                break;
            }
            d*=10;
            l++;
        }
    }

    return(0);
}

The value[] array holds ten numbers progressing from 1 through 1234567890. A for loop churns through each of the values.

Within the for loop, a while loop compares value[x] with successive powers of 10. The looping value d starts at one, and multiplies itself by 10 each iteration until its value equals 10,000,000,000.

Within the while loop, an if statement compares the value submitted, value[x], with d, the power of 10. When the value is less, then digit counter variable l (little L) determines the number of digits. Here is the output:

1 is 1 digits long
12 is 2 digits long
123 is 3 digits long
1234 is 4 digits long
12345 is 5 digits long
123456 is 6 digits long
1234567 is 7 digits long
12345678 is 8 digits long
123456789 is 9 digits long
1234567890 is 10 digits long

This test works fine, but what I truly adore is generating random numbers to try the code. The problem here is that random values are typically and uniformly huge, so they must be pared down to a smaller length. Such an exercise requires more math magic, at which I confess to being a poor conjurer. Still, I took a stab at it in this update to the code:

2022_08_20-Lesson-b.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int main()
{
    long d;
    int l,r;
    long value;

    /* seed the randomizer */
    srand( (unsigned)time(NULL) );

    /* obtain the random value */
    value = rand();

    /* obtain a random value length */
    r = rand() % 11;

    /* truncate the value */
    value %= (int)pow(10,r);

    /*
        now count the digits, which will end
        up being the same value as 'r', but
        what-the-hey
    */
    l=d=1;
    while( d<=10000000000 )
    {
        if( value<d )
        {
            printf("%ld is %d digits long\n",value,l-1);
            break;
        }
        d*=10;
        l++;
    }

    return(0);
}

Two random values are required to generate a random number of a random length. The first is the value itself, value in the above code. The second is the truncating value, r above.

At Line 22, value is truncated by taking r to the power of 10, typecasting it as an integer, and using the mod assignment operator, %=. This expression reduces the random value down to a digit range equal to the value of r — which is what the remainder of the code attempts to discover. Still, the point is to try the technique on a random value, and it works:

36398 is 5 digits long
9070012 is 7 digits long
99086819 is 8 digits long
599137240 is 9 digits long
4 is 1 digits long

I would bet a whole donut that a better way exists to count the digits in a number. If not a better way, perhaps even a different way that makes more sense. If you know of one, please let me know. I’m not desperate, just curious.

5 thoughts on “Counting the Digits

  1. I think you should be able to do something with logarithms (base 10).

    Why did you think it necessary to specify “whole” donut? I don’t think anyone would assume you meant a half eaten one 🙂

  2. Yep, there’s that maths thing: I would never assume logarithms because it was two week of school and then we moved on. I looked for a book on logarithms a while back. Nada. The only one I found was tepid.

    Donuts are precious.

  3. This is a selection of numbers with their base 10 logarithms:

    1 – 0
    2 – 0.301030
    9 – 0.954243

    10 – 1
    99 – 1.995635

    100 – 2
    999 – 2.999565

    1000 – 3
    9999 – 3.999957

    10000 – 4
    99999 – 4.999996

    100000 – 5
    999999 – 5.999999

    so all you need to do is round the logarithm down to the nearest integer and add 1, eg

    digits = floor(log10(n)) + 1;

  4. I’m not professional programmer, but this type of problems, counting digits in a number, i’ve always done it this way:

    long number;
    int digits = 0;
    while (number)
    {
    digits++;
    number /= 10;
    }

Leave a Reply