Finding the length of an integer in C
Asked Answered
C

30

93

I would like to know how I can find the length of an integer in C.

For instance:

  • 1 => 1
  • 25 => 2
  • 12512 => 5
  • 0 => 1

and so on.

How can I do this in C?

Carree answered 18/6, 2010 at 9:8 Comment(8)
What's the definition of "length" if the integer is 0? Negative?Jezabella
See #680102. It's almost a duplicate, but not exact as it's a .NET question.Mitman
the right question is not the length of the integer, but which is the minimal number of decimal digits needed to represent that number (held into a C int). log10 is your friend: log10(10000) = 4, +1 the number of digits (log10 must be truncated)... if the num is neg, you need one more for the - symbol, if you want to count it, and log10(-num) (since log of a neg number is "problematic".Quintile
How sure are you that log10(10000) will return 4 and not 3.999999...?Ceporah
Hmm. Experiment shows that log10(10**n) yields the exact value for powers of 10 from 1 to 2**19, at least with gcc and glibc. But I wouldn't count on it for all implementations. (** denotes exponentiation; there's no such operator in C.)Ceporah
Duplicate: #1069349Sustentation
@Byway Whoa! I just flagged this same question as a duplicate. You must be a person, too.Byway
For a second I almost thought I ended up on Code Golf instead of SONewsprint
D
134

C:

You could take the base-10 log of the absolute value of the number, round it down, and add one. This works for positive and negative numbers that aren't 0, and avoids having to use any string conversion functions.

The log10, abs, and floor functions are provided by math.h. For example:

int nDigits = floor(log10(abs(the_integer))) + 1;

You should wrap this in a clause ensuring that the_integer != 0, since log10(0) returns -HUGE_VAL according to man 3 log.

Additionally, you may want to add one to the final result if the input is negative, if you're interested in the length of the number including its negative sign.

Java:

int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;

N.B. The floating-point nature of the calculations involved in this method may cause it to be slower than a more direct approach. See the comments for Kangkan's answer for some discussion of efficiency.

Daugava answered 18/6, 2010 at 9:13 Comment(9)
Actually you should use floor and add 1 instead. Math.Ceil(Math.Log(99)) = 2 but Math.Ceil(Math.Log(10)) = 1. Math.Floor(Math.Log(99)) + 1 = 2 and Math.Floor(Math.Log(10)) = 2Bummer
The question isn't entirely clear on the definition of length (so you could possibly have thought 'number of digits excluding leading zeros'), but I would expect 0 and -1 to return 1 and 2 as the length of their character representation rather than -2147483648 and 1.Gamut
@Pete Thanks for reminding me about log's domain limitation and the negative number case - I've edited my answer.Daugava
+1 nice & short - this is my preferred answer, even if it's the slowest - after all, the speed difference isn't huge and this kind of code is very unlikely to be a perf. bottleneck anyhow.Uncivilized
+1 for the Note (and following comments) about efficiency. Every programmer should know basic math indeed, but should also know sometimes math isn't the faster route thanks to friggin' fast binary processors. Talking about C, this can easily become a bottleneck.Brasilin
This does not work for 999999999999999999, a C integer that will be converted to a greater double value, and thus produce an erroneous count of digits. The OP did not specify int, just integer.Aguish
Addressing the == 0 case, here is a one-liner: (the_integer == 0 ? 1 : (int)floor(log10(abs(the_integer))) + 1)Domoniquedomph
Sweet! For a large number I modified like so: long long nDigits = floor(log10(llabs(the_integer))) + 1;Chromatism
abs is provided by stdlib, not by mathJemison
U
64

If you're interested in a fast and very simple solution, the following might be quickest (this depends on the probability distribution of the numbers in question):

int lenHelper(unsigned x) {
    if (x >= 1000000000) return 10;
    if (x >= 100000000)  return 9;
    if (x >= 10000000)   return 8;
    if (x >= 1000000)    return 7;
    if (x >= 100000)     return 6;
    if (x >= 10000)      return 5;
    if (x >= 1000)       return 4;
    if (x >= 100)        return 3;
    if (x >= 10)         return 2;
    return 1;
}

int printLen(int x) {
    return x < 0 ? lenHelper(-x) + 1 : lenHelper(x);
}

While it might not win prizes for the most ingenious solution, it's trivial to understand and also trivial to execute - so it's fast.

On a Q6600 using MSC I benchmarked this with the following loop:

int res = 0;
for(int i = -2000000000; i < 2000000000; i += 200) res += printLen(i);

This solution takes 0.062s, the second-fastest solution by Pete Kirkham using a smart-logarithm approach takes 0.115s - almost twice as long. However, for numbers around 10000 and below, the smart-log is faster.

At the expense of some clarity, you can more reliably beat smart-log (at least, on a Q6600):

int lenHelper(unsigned x) { 
    // this is either a fun exercise in optimization 
    // or it's extremely premature optimization.
    if(x >= 100000) {
        if(x >= 10000000) {
            if(x >= 1000000000) return 10;
            if(x >= 100000000) return 9;
            return 8;
        }
        if(x >= 1000000) return 7;
        return 6;
    } else {
        if(x >= 1000) {
            if(x >= 10000) return 5;
            return 4;
        } else {
            if(x >= 100) return 3;
            if(x >= 10) return 2;
            return 1;
        }
    }
}

This solution is still 0.062s on large numbers, and degrades to around 0.09s for smaller numbers - faster in both cases than the smart-log approach. (gcc makes faster code; 0.052 for this solution and 0.09s for the smart-log approach).

Uncivilized answered 18/6, 2010 at 12:33 Comment(4)
I shudder to think what the second version would look like written entirely with the ternary operator...Uncivilized
If this was used to munch through long lists of numbers the amount of branching code would cause havoc with the CPUs branch prediction and not produce the fastest execution Im afraid.Saxen
In my benchmark it's still the fastest solution - note that all other integral solutions also require several branches, and the only real alternative is an int-to-double conversion with a floating point log (which as it turns out isn't cheap either).Uncivilized
@earthdan: that solution is fine, but quite slow due to the divisions. It also always uses more branches that the second version of this code, and more on average than the first solution posted here. Also, that solution is quite clever (in a bad way) in that the reason it works isn't entirely obvious. If you want a short+obvious solution, use https://mcmap.net/q/223897/-finding-the-length-of-an-integer-in-c; if you want a fast and obvious solution use this. Can't imagine the use case for https://mcmap.net/q/225555/-finding-the-number-of-digits-of-an-integer (though it's of course a fun intellectual exercise!)Uncivilized
G
40
int get_int_len (int value){
  int l=1;
  while(value>9){ l++; value/=10; }
  return l;
}

and second one will work for negative numbers too:

int get_int_len_with_negative_too (int value){
  int l=!value;
  while(value){ l++; value/=10; }
  return l;
}
Genevagenevan answered 18/6, 2010 at 9:11 Comment(4)
I like this. No temporary character buffers with assumptions about the size.Wehrmacht
Quick and elegant, however, this won't work for negative numbers. Don't know if that's a concern for the question posterJasonjasper
it will. give it a try. it will return 1Genevagenevan
You're right - it will indeed :-). It'd be clearer to me (and no slower) to distinguish that case via an if-return rather than a negation.Uncivilized
M
22

You can write a function like this:

unsigned numDigits(const unsigned n) {
    if (n < 10) return 1;
    return 1 + numDigits(n / 10);
}
Marsden answered 18/6, 2010 at 9:12 Comment(15)
This is unnecessarily inefficient - why use up to around 18 recursive function calls when you can do it with one call to log10?Daugava
but making it not recursive could be in some circumstances, depending on the cpus and availability of float coprocessor, faster than using a fuction like log10Quintile
@Jordan Lewis calling this 20 million times takes 1.8s on my netbook; calling your code takes 6.6 seconds (gcc -O3 for both). One call to log10 is very much slower than all the recursive calls this makes.Gamut
@Pete I see .001s for the log10 version and .44s for the recursive version on my Intel i7, for 20 million times with -O3.Daugava
@Jordan are you calling it with the same or different values? ` int c = 0; for ( int i = -10000000; i < 10000000; ++i ) c += printed_length(i); printf ( "total %d\n", c); `Gamut
@Pete I was iterating from i = 0 to 2 million, and using i as the parameter to printed_length as well. I will try again with your parameters, including the +=.Daugava
Well, surely you weren't using this numDigits implementation for the negative values, as it doesn't handle negative values?Daugava
@Pete and @Jordan thanks for bringing in the context of efficiency. I proposed my answer looking at the simplicity.Marsden
@Jordan I added if ( x < 0 ) return 1 + printed_length ( -x ); to the start of itGamut
@Pete I must have made a mistake causing the compiler to optimize out the actual calls before. I now observe a gap like yours - .26 seconds for the recursive version, and 1.68 seconds for the floating point arithmetic version. Interesting!Daugava
Quite possibly the recursive version is less recursive that it looks once compiled - depending on version/options, gcc will partially unroll short recursive calls like this; that's particularly easy here since it's a tail call.Uncivilized
@Eamon Nerbonne the 1 + part stops it being a trivial tail call.Gamut
@Pete: indeed; not trivial; still inlinable though; and with a maximum depth of a dozen or so inlining would work well.Uncivilized
gcc unrolls it (at least gcc 4.8 does) 16 instructions with -O2, so it's really the best solution, even better than log and better then the len helper which has a lot of compares (keyword: branch prediction)Lofton
@Jordan Lewis looks like log()/floor nor logl()/floorl() will work with long integer values. here a test: minimum signed long integer on this system is: -9223372036854775808 maximum signed long integer on this system is: 9223372036854775807 get_num_len2() i=-9223372036854775808 len=-2147483648 get_num_len2() i=-9223372036854775807 len=2Prae
E
12

length of n:

length =  ( i==0 ) ? 1 : (int)log10(n)+1;
Exhortative answered 18/6, 2010 at 9:14 Comment(6)
You should probably avoid rounding via casting and instead go or a more explicit (a.k.a. portable and consistent) rounding approach.Competition
how is casting implemented? how a function like floor can be implemented? (we are assuming a processor with ieee in hardware, or through a math coprocessor, or the availability of software function to perform the same function normally present on fp-capable processors)... at the end (int) is portable and consistent in most cases (I dare say, all the cases we normally care of)Quintile
As mentioned in other posts, this will fail when n = 0Jasonjasper
@Lutz: what kind of portability are you buying by assuming casting from double to int is undefined? Is there actually a relevant platform where this is the case?Uncivilized
@Chris Lutz If it's a standards compliant C implementation, then it obeys When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero).Gamut
@Pete, @Eamon - My bad. I thought it was undefined or implementation defined.Competition
B
8

The number of digits of an integer x is equal to 1 + log10(x). So you can do this:

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

int main()
{
    int x;
    scanf("%d", &x);
    printf("x has %d digits\n", 1 + (int)log10(x));
}

Or you can run a loop to count the digits yourself: do integer division by 10 until the number is 0:

int numDigits = 0;
do
{
    ++numDigits;
    x = x / 10;
} while ( x );

You have to be a bit careful to return 1 if the integer is 0 in the first solution and you might also want to treat negative integers (work with -x if x < 0).

Basseterre answered 18/6, 2010 at 9:14 Comment(1)
Yes, a nice simple do loop.Humour
B
8

A correct snprintf implementation:

int count = snprintf(NULL, 0, "%i", x);
Berlioz answered 9/4, 2011 at 12:15 Comment(2)
What happens if x is negative?Casual
Then count will have one extra unit for the minus sign.Berlioz
G
7

The most efficient way could possibly be to use a fast logarithm based approach, similar to those used to determine the highest bit set in an integer.

size_t printed_length ( int32_t x )
{
    size_t count = x < 0 ? 2 : 1;

    if ( x < 0 ) x = -x;

    if ( x >= 100000000 ) {
        count += 8;
        x /= 100000000;
    }

    if ( x >= 10000 ) {
        count += 4;
        x /= 10000;
    }

    if ( x >= 100 ) {
        count += 2;
        x /= 100;
    }

    if ( x >= 10 )
        ++count;

    return count;
}

This (possibly premature) optimisation takes 0.65s for 20 million calls on my netbook; iterative division like zed_0xff has takes 1.6s, recursive division like Kangkan takes 1.8s, and using floating point functions (Jordan Lewis' code) takes a whopping 6.6s. Using snprintf takes 11.5s, but will give you the size that snprintf requires for any format, not just integers. Jordan reports that the ordering of the timings are not maintained on his processor, which does floating point faster than mine.

The easiest is probably to ask snprintf for the printed length:

#include <stdio.h>

size_t printed_length ( int x )
{
    return snprintf ( NULL, 0, "%d", x );
}

int main ()
{
    int x[] = { 1, 25, 12512, 0, -15 };

    for ( int i = 0; i < sizeof ( x ) / sizeof ( x[0] ); ++i )
        printf ( "%d -> %d\n", x[i], printed_length ( x[i] ) );

    return 0;
}
Gamut answered 18/6, 2010 at 9:16 Comment(7)
If you're going to use snprintf(), why not snprintf(NULL, 0, "%d", x) and not write anything? (At the very least, use a static buffer in your function.)Competition
because I haven't had enough coffee yet this morning, and was thinking about the first leg of the answer.Gamut
Should split your replies in two posts, I'd +1 the first one but not the 2nd.Steakhouse
It rather depends why you want the length - if you want to know how many chars snprintf will require, you're better off using snprintf; if you want silly optimised code, you might want the first one.Gamut
" C99 allows str to be NULL in this case [the case of n==0], and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough" so it is ok, why notQuintile
(Ah... I suppose the answer was modified, following Lutz's suggestion... ?)Quintile
Your solution does not work for INT_MIN. Use a local unsigned variable for the tests and initialize it with x >= 0 ? x : -(unsigned)xAguish
J
6

Yes, using sprintf.

int num;
scanf("%d",&num);
char testing[100];
sprintf(testing,"%d",num);
int length = strlen(testing);

Alternatively, you can do this mathematically using the log10 function.

int num;
scanf("%d",&num);
int length;
if (num == 0) {
  length = 1;
} else {    
  length = log10(fabs(num)) + 1;
  if (num < 0) length++;
}
Jasonjasper answered 18/6, 2010 at 9:10 Comment(5)
No, that's actually rather dangerous and prone to errors. You should use snprintf() so you don't have to write (and risk overflowing) anything.Competition
Assuming he was referring to a C integer (not a bignum type) there won't be any issues with overflows.Jasonjasper
There will be issues when computers get bigger. Sure, you'll need a 512 bit computer to break your code, but they'll probably make one someday.Competition
no, likely 128 bit will be the last frontier... there won't be any reason to go beyond (exagerating, I say there's no reason for going beyond 64 bits, but I am almost already wrong, but currently no real 128bit processor are available yet, and they hardly will be, at least in consumer computing... I hope, since the they will need them, it would mean O.S. will be too fat and we'll remember these days as better days)Quintile
you can simply use the return value of sprintf() without calling strlen()Readership
V
5
int digits=1;

while (x>=10){
    x/=10;
    digits++;
}
return digits;
Vivl answered 14/2, 2015 at 8:22 Comment(0)
N
3
sprintf(s, "%d", n);
length_of_int = strlen(s);
Nichellenichol answered 18/6, 2010 at 9:31 Comment(0)
R
2

You may use this -

(data_type)log10(variable_name)+1

ex:

len = (int)log10(number)+1;

Retinue answered 31/1, 2017 at 7:42 Comment(0)
S
2

In this problem , i've used some arithmetic solution . Thanks :)

int main(void)
{
    int n, x = 10, i = 1;
    scanf("%d", &n);
    while(n / x > 0)
    {
        x*=10;
        i++;
    }
    printf("the number contains %d digits\n", i);

    return 0;
}
Sweat answered 5/12, 2020 at 21:38 Comment(0)
L
2

Similar to all answers here, if you are already using string.h, you can do the sprintf right at macro, instead of having separate function:

#define DIGIT_COUNT(x) (snprintf(NULL, 0, "%d", (x)))

This macro will count negative sign towards digit. If you don't want that, you can simply use abs function:

#define DIGIT_COUNT(x) (snprintf(NULL, 0, "%d", abs((x))))
Levin answered 16/5, 2023 at 10:17 Comment(0)
C
1

Quite simple

int main() {
    int num = 123;
    char buf[50];

    // convert 123 to string [buf]
    itoa(num, buf, 10);

    // print our string
    printf("%s\n", strlen (buf));

    return 0;
}
Concordat answered 18/6, 2010 at 9:11 Comment(1)
it can be easily written howeverQuintile
S
1

keep dividing by ten until you get zero, then just output the number of divisions.

int intLen(int x)
{
  if(!x) return 1;
  int i;
  for(i=0; x!=0; ++i)
  {
    x /= 10;
  }
  return i;
}
Soong answered 18/6, 2010 at 9:13 Comment(3)
This is incorrect. This will return an arbitrary number if x = 0.Jasonjasper
Bet it won't... It will however return the wrong value for 0.Steakhouse
@phleet, I'm pretty sure the semicolon after i=0 is a sequence point, but zero is still the wrong output. It's fixed now though.Soong
S
1

This goes for both negative and positive intigers

    int get_len(int n)
    {
        if(n == 0)
        return 1;

        if(n < 0)    
        {
           n = n * (-1); // if negative
        }

        return  log10(n) + 1;
    }

Same logic goes for loop

  int get_len(int n)
  {
       if(n == 0)
       return 1;

       int len = 0;
       if(n < 0)
       n = n * (-1);

       while(n > 1)
       {
          n /= 10;
          len++;
       }

       return len;
  }
Swen answered 23/10, 2018 at 22:15 Comment(0)
C
1

For simple programs...

int num = 456, length=0 // or read value from the user to num
while(num>0){
    num=num/10;
    length++;
}

Use another variable to retain the initial num value.

Credo answered 6/10, 2021 at 14:4 Comment(0)
N
1

Hmm, maybe like this...?

#define _LEN(x) (sizeof(#x)/sizeof(char)-1)
Nygaard answered 9/2, 2022 at 4:24 Comment(1)
This will work only and only if the constant number (ex. 123) is given to macro. If it is arithmetic or int variable, this macro will failLevin
A
0

In my opinion the shortest and easiest solution would be:

int length , n;

printf("Enter a number: ");

scanf("%d", &n);

length = 0;

while (n > 0) {
   n = n / 10;
   length++;
}

printf("Length of the number: %d", length);
Alva answered 4/1, 2014 at 15:7 Comment(1)
If (n) equals 0, this will return length of (n) as 0. Use do...while so loop is executed once when (n) equals 0.Esque
M
0

My way:

Divide as long as number is no more divisible by 10:

u8 NumberOfDigits(u32 number)
{
    u8 i = 1;
    while (number /= 10) i++;

    return i;
}

I don't know how fast is it in compared with other propositions..

Mcafee answered 12/9, 2014 at 7:13 Comment(0)
S
0
int intlen(int integer){
    int a;
    for(a = 1; integer /= 10; a++);
    return a;
}
Swash answered 26/10, 2014 at 20:6 Comment(0)
O
0

A more verbose way would be to use this function.

int length(int n)
{
    bool stop;
    int nDigits = 0;
    int dividend = 1;
    do
    {
        stop = false;
        if (n > dividend)
        {
            nDigits = nDigits + 1;
            dividend = dividend * 10;
        }
        else {
            stop = true;
        }


    }
    while (stop == false);
    return nDigits;
}
Oldster answered 18/8, 2018 at 7:14 Comment(0)
R
0
int returnIntLength(int value){
    int counter = 0;
    if(value < 0)
    {
        counter++;
        value = -value;
    }
    else if(value == 0)
        return 1;

    while(value > 0){
        value /= 10;
        counter++;
    }

    return counter;
}

I think this method is well suited for this task:

value and answers:

  • -50 -> 3 //it will count - as one character as well if you dont want to count minus then remove counter++ from 5th line.

  • 566666 -> 6

  • 0 -> 1

  • 505 -> 3

Ruse answered 25/12, 2018 at 7:4 Comment(0)
C
0

Why don't you cast your integer to String and get length like this :

int data = 123;
int data_len = String(data).length();
Cooker answered 2/2, 2021 at 17:36 Comment(1)
Whatever language that it is, it isn't standard C as asked for in the question.Morette
K
0

Solution

Use the limit where the integer length changes, in the case of the decimal it is a power of 10, and thus use a counter for each verification that the specified integer has not exceeded the limit.

With the math.h dependency:

#include <math.h>

int count_digits_of_integer(unsigned int integer) {
    int count = 1;

    while(1) {
        int limit = pow(10, count);
        if(integer < limit) break;
        count++;

    }

    return count;
}

Without dependency:

int int_pow(int base, int exponent) {
    int potency = base;

    for(int i = 1; i < exponent; i++) potency *= base;

    return potency;

}

int count_digits_of_integer(unsigned int integer) {
    int count = 1;
    
    while(1) {
        int limit = int_pow(10, count);
        if(integer < limit) break;
        count++;

    }
    
    return count;
}

Implementation

#include <stdio.h>

// Copy and paste the solution code here

int main() {
    
    printf("%i -> (%i digits)\n", 0, count_digits_of_integer(0));
    printf("%i -> (%i digits)\n", 12, count_digits_of_integer(12));
    printf("%i -> (%i digits)\n", 34569, count_digits_of_integer(34569));
    printf("%i -> (%i digits)\n", 1234, count_digits_of_integer(1234));
    printf("%i -> (%i digits)\n", 3980000, count_digits_of_integer(3980000));
    printf("%i -> (%i digits)\n", 100, count_digits_of_integer(100));
    printf("%i -> (%i digits)\n", 9, count_digits_of_integer(9));
    printf("%i -> (%i digits)\n", 385784, count_digits_of_integer(385784));
    
    return 0;
}

Output:

0 -> (1 digits)
12 -> (2 digits)
34569 -> (5 digits)
1234 -> (4 digits)
3980000 -> (7 digits)
100 -> (3 digits)
9 -> (1 digits)
385784 -> (6 digits)
Konstantin answered 16/10, 2021 at 1:50 Comment(0)
A
-1

I think I got the most efficient way to find the length of an integer its a very simple and elegant way here it is:

int PEMath::LengthOfNum(int Num)
{
int count = 1;  //count starts at one because its the minumum amount of digits posible
if (Num < 0)
{
    Num *= (-1);
}

for(int i = 10; i <= Num; i*=10)
{
     count++;
}      
return count;
                // this loop will loop until the number "i" is bigger then "Num"
                // if "i" is less then "Num" multiply "i" by 10 and increase count
                // when the loop ends the number of count is the length of "Num".
}
Agincourt answered 19/5, 2013 at 6:56 Comment(2)
Num *= (-1) seems a bit heavy handed, although your compiler will probably optimize it to the much more efficient Num = -Num. Note that multiplication is often an expensive operation whereas negating an integer is pretty trivial.Outrage
Not C code. Does not work for INT_MIN, does not work for INT_MAX either, actually does not work for numbers larger or equal to the largest power of 10 less than INT_MAX, such as 1000000000 for int32_t.Aguish
G
-1

int main(void){ unsigned int n, size=0;

printf("get the int:");
scanf("%u",&n);

/*the magic*/
for(int i = 1; n >= i; i*=10){
    size++;
}

printf("the value is: %u \n", n);
printf("the size is: %u \n", size);

return 0;

}

Gers answered 13/9, 2018 at 4:4 Comment(0)
V
-1

You can also use this function to find the length of an integer:

int countlength(int number)
{
    static int count = 0;
    if (number > 0)
    {
        count++;
        number /= 10;
        countlength(number);
    }
    return count;
}
Vaivode answered 20/9, 2022 at 11:36 Comment(2)
This function will only work once. On a second 'top level' call, the count will not get reset to zero.Toft
static inside of the function keeps the value for future function calls. For this type of recursion it seems it is needed, but as Adrian said, it will work only once,Levin
U
-2
#include  <stdio.h>
int main(void){
    int c = 12388884;
    printf("length of integer is: %d",printf("%d",c));
    return 0;
}
Unshackle answered 8/1, 2019 at 6:11 Comment(1)
Your solution seems to print also the number itself and not just it's length!Hurry

© 2022 - 2024 — McMap. All rights reserved.