21

How do I detect the length of an integer? In case I had le: int test(234567545);

How do I know how long the int is? Like telling me there is 9 numbers inside it???

*I have tried:**

char buffer_length[100];


    //  assign directly to a string.

    sprintf(buffer_length, "%d\n", 234567545);

    string sf = buffer_length;


    cout <<sf.length()-1 << endl;

But there must be a simpler way of doing it or more clean...

user1417815
  • 445
  • 3
  • 7
  • 16
  • 7
    Just a thought: How should negative numbers be handled? – Joey Jun 22 '12 at 07:32
  • 3
    Why do you need `std::string` here? You could just do a `strlen(buffer_length)`. You also don't need the `\n` and thus no `-1`. – leemes Jun 26 '12 at 23:22
  • Possible duplicate of : http://stackoverflow.com/questions/1489830/efficient-way-to-determine-number-of-digits-in-an-integer – Rishi Feb 06 '17 at 09:18
  • 5
    C and C++ are different programming languages. A number does not have digits, only its decimal representation has digits. – Basile Starynkevitch Feb 26 '17 at 10:13
  • Simple, use the `snprintf()` trick, `int needed = snprintf (NULL, 0, "%d", 234567545);` See [man 3 printf](https://man7.org/linux/man-pages/man3/printf.3.html) Under "RETURN VALUE" second paragraph second sentence specifically. – David C. Rankin Jan 27 '23 at 06:08

10 Answers10

44

How about division:

int length = 1;
int x = 234567545;
while ( x /= 10 )
   length++;

or use the log10 method from <math.h>.

Note that log10 returns a double, so you'll have to adjust the result.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
11

Make a function :

int count_numbers ( int num) {
   int count =0;
   while (num !=0) {   
      count++;  
      num/=10;
   } 
   return count;
}
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
Shehzad Bilal
  • 2,535
  • 2
  • 18
  • 27
9

Nobody seems to have mentioned converting it to a string, and then getting the length. Not the most performant, but it definitely does it in one line of code :)

int num = -123456;
int len = to_string(abs(num)).length();

cout << "LENGTH of " << num << " is " << len << endl;    
// prints "LENGTH of 123456 is 6"
jmg
  • 617
  • 9
  • 13
5

You can use stringstream for this as shown below

stringstream ss;
int i = 234567545;
ss << i;
cout << ss.str().size() << endl;
Sanish
  • 1,699
  • 1
  • 12
  • 21
4

if "i" is the integer, then

int len ;

char buf[33] ;

itoa (i, buf, 10) ; // or maybe 16 if you want base-16 ?

len = strlen(buf) ;

if(i < 0)
    len-- ;    // maybe if you don't want to include "-" in length ?
Thorsen
  • 403
  • 1
  • 4
  • 10
4
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {

    int i=2384995;
    char buf[100];

    itoa(i, buf, 10); // 10 is the base decimal

    printf("Lenght: %d\n", strlen(buf));


    return 0;
}

Beware that itoa is not a standard function, even if it is supported by many compilers.

A_nto2
  • 1,106
  • 7
  • 16
2

len=1+floor(log10(n));//c++ code lib (cmath)

congar
  • 229
  • 3
  • 8
1

looking across the internet it's common to make the mistake of initializing the counter variable to 0 and then entering a pre-condition loop testing for as long as the count does not equal 0. a do-while loop is perfect to avoid this.

    unsigned udc(unsigned u) //unsigned digit count
    {
      unsigned c = 0;
      do
        ++c;
      while ((u /= 10) != 0);
      return c;
    }

it's probably cheaper to test whether u is less than 10 to avoid the uneccessary division, increment, and cmp instructions for cases where u < 10.

but while on that subject, optimization, you could simply test u against constant powers of ten.

    unsigned udc(unsigned u) //unsigned digit count
    {
      if (u < 10)   return 1;
      if (u < 100)  return 2;
      if (u < 1000) return 3;
      //...
      return 0; //number was not supported
    }

which saves you 3 instructions per digit, but is less adaptable for different radixes inaddition to being not as attractive, and tedious to write by hand, in which case you'd rather write a routine to write the routine before inserting it into your program. because C only supports very finite numbers, 64bit,32bit,16bit,8bit, you could simply limit yourself to the maximum when generating the routine to benefit all sizes.

to account for negative numbers, you'd simply negate u if u < 0 before counting the number of digits. of course first making the routine support signed numbers.

if you know that u < 1000, it's probably easier to just write, instead of writing the routine.

   if (u > 99) len = 3;
   else
   if (u > 9)  len = 2;
   else        len = 1;
Anonymous
  • 11
  • 2
0

Here are a few different C++ implementations* of a function named digits() which takes a size_t as argument and returns its number of digits. If your number is negative, you are going to have to pass its absolute value to the function in order for it to work properly:

The While Loop

int digits(size_t i)
{
    int count = 1;
    while (i /= 10) {
        count++;
    }
    return count;
}

The Exhaustive Optimization Technique

int digits(size_t i) {
    if (i > 9999999999999999999ull) return 20;
    if (i > 999999999999999999ull) return 19;
    if (i > 99999999999999999ull) return 18;
    if (i > 9999999999999999ull) return 17;
    if (i > 999999999999999ull) return 16;
    if (i > 99999999999999ull) return 15;
    if (i > 9999999999999ull) return 14;
    if (i > 999999999999ull) return 13;
    if (i > 99999999999ull) return 12;
    if (i > 9999999999ull) return 11;
    if (i > 999999999ull) return 10;
    if (i > 99999999ull) return 9;
    if (i > 9999999ull) return 8;
    if (i > 999999ull) return 7;
    if (i > 99999ull) return 6;
    if (i > 9999ull) return 5;
    if (i > 999ull) return 4;
    if (i > 99ull) return 3;
    if (i > 9ull) return 2;
    return 1;  
}

The Recursive Way

int digits(size_t i) { return i < 10 ? 1 : 1 + digits(i / 10); }

Using snprintf() as a Character Counter

⚠ Requires #include <stdio.h> and may incur a significant performance penalty compared to other solutions. This method capitalizes on the fact that snprintf() counts the characters it discards when the buffer is full. Therefore, with the right arguments and format specifiers, we can force snprintf() to give us the number of digits of any size_t.

int digits(size_t i) { return snprintf (NULL, 0, "%llu", i); }

The Logarithmic Way

⚠ Requires #include <cmath> and is unreliable for unsigned integers with more than 14 digits.

// WARNING! There is a silent implicit conversion precision loss that happens
// when we pass a large int to log10() which expects a double as argument.
int digits(size_t i) { return !i? 1 : 1 + log10(i); }

Driver Program

You can use this program to test any function that takes a size_t as argument and returns its number of digits. Just replace the definition of the function digits() in the following code:

#include <iostream>
#include <stdio.h>
#include <cmath>
#include <chrono>
using std::cout;
using namespace std::chrono;

// REPLACE this function definition with the one you want to test.
int digits(size_t i)
{
    int count = 1;
    while (i /= 10) {
        count++;
    }
    return count;
}

// driver code
int main ()
{
    const int max = digits(~0ull);
    size_t i = 0, d;
    do {
        auto t0 = high_resolution_clock::now();
        d = digits(i);
        auto t1 = high_resolution_clock::now();
        duration<double, std::nano> te = t1 - t0;
        cout << i << " has " << d << " digits (" << te.count() << " ns).\n";
        i = d < max ? (!i ? 9 : 10 * i - 1) : ~0ull;
        t0 = high_resolution_clock::now();
        d = digits(i);
        t1 = high_resolution_clock::now();
        te = t1 - t0;
        cout << i << " has " << d << " digits (" << te.count() << " ns).\n";
    } while (++i);
}

* Everything was tested on a Windows 10 (64-bit) machine using GCC 12.2.0 in Visual Studio Code.

q-l-p
  • 4,304
  • 3
  • 16
  • 36
  • What is the result? Which is the fastest? – Tom Tom Apr 06 '23 at 14:29
  • @TomTom I have modified the driver code to display the time it takes for the function to return the number of digits. I wasn't able to find out which is the fastest. Can you tell me your use case? – q-l-p Apr 07 '23 at 17:06
  • I need to count the digit from a function, which the result is a float. 10'000 random values, range between FLOAT_MAX.. FLOAT_MIN. – Tom Tom Apr 10 '23 at 20:53
0

As long as you are mixing C stdio and C++ iostream, you can use the snprintf NULL 0 trick to get the number of digits in the integer representation of the number. Specifically, per man 3 printf If the string exceeds the size parameter provided and is truncated snprintf() will return

   ... the number of characters (excluding the terminating null byte)
   which would have been written to the final string if enough space
   had been available.

This allows snprintf() to be called with the str parameter NULL and the size parameter 0, e.g.

    int ndigits = snprintf (NULL, 0, "%d", 234567545)

In your case where you simply wish to output the number of digits required for the representation, you can simply output the return, e.g.

#include <iostream>
#include <cstdio>

int main() {

  std::cout << "234567545 is " << snprintf (NULL, 0, "%d", 234567545) <<
               " characters\n";

}

Example Use/Output

$ ./bin/snprintf_trick
234567545 is 9 characters

note: the downside to using the snprintf() trick is that you must provide the conversion specifier which will limit the number of digits representable. E.g "%d" will limit to int values while "%lld" would allow space for long long values. The C++ approach using std::stringstream while still limited to numeric conversion using the << operator handles the different integer types without manually specifying the conversion. Something to consider.

second note: you shouldn't dangle the "\n" of the end of your sprintf() conversion. Add the new line as part of your output and you don't have to subtract 1 from the length...

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85