How to find length of digits in an integer?

Viewed 639975

In Python, how do you find the number of digits in an integer?

30 Answers

If you want the length of an integer as in the number of digits in the integer, you can always convert it to string like str(133) and find its length like len(str(123)).

Without conversion to string

import math
digits = int(math.log10(n))+1

To also handle zero and negative numbers

import math
if n > 0:
    digits = int(math.log10(n))+1
elif n == 0:
    digits = 1
else:
    digits = int(math.log10(-n))+2 # +1 if you don't count the '-' 

You'd probably want to put that in a function :)

Here are some benchmarks. The len(str()) is already behind for even quite small numbers

timeit math.log10(2**8)
1000000 loops, best of 3: 746 ns per loop
timeit len(str(2**8))
1000000 loops, best of 3: 1.1 µs per loop

timeit math.log10(2**100)
1000000 loops, best of 3: 775 ns per loop
 timeit len(str(2**100))
100000 loops, best of 3: 3.2 µs per loop

timeit math.log10(2**10000)
1000000 loops, best of 3: 844 ns per loop
timeit len(str(2**10000))
100 loops, best of 3: 10.3 ms per loop

It's been several years since this question was asked, but I have compiled a benchmark of several methods to calculate the length of an integer.

def libc_size(i): 
    return libc.snprintf(buf, 100, c_char_p(b'%i'), i) # equivalent to `return snprintf(buf, 100, "%i", i);`

def str_size(i):
    return len(str(i)) # Length of `i` as a string

def math_size(i):
    return 1 + math.floor(math.log10(i)) # 1 + floor of log10 of i

def exp_size(i):
    return int("{:.5e}".format(i).split("e")[1]) + 1 # e.g. `1e10` -> `10` + 1 -> 11

def mod_size(i):
    return len("%i" % i) # Uses string modulo instead of str(i)

def fmt_size(i):
    return len("{0}".format(i)) # Same as above but str.format

(the libc function requires some setup, which I haven't included)

size_exp is thanks to Brian Preslopsky, size_str is thanks to GeekTantra, and size_math is thanks to John La Rooy

Here are the results:

Time for libc size:      1.2204 μs
Time for string size:    309.41 ns
Time for math size:      329.54 ns
Time for exp size:       1.4902 μs
Time for mod size:       249.36 ns
Time for fmt size:       336.63 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.240835x)
+ math_size (1.321577x)
+ fmt_size (1.350007x)
+ libc_size (4.894290x)
+ exp_size (5.976219x)

(Disclaimer: the function is run on inputs 1 to 1,000,000)

Here are the results for sys.maxsize - 100000 to sys.maxsize:

Time for libc size:      1.4686 μs
Time for string size:    395.76 ns
Time for math size:      485.94 ns
Time for exp size:       1.6826 μs
Time for mod size:       364.25 ns
Time for fmt size:       453.06 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.086498x)
+ fmt_size (1.243817x)
+ math_size (1.334066x)
+ libc_size (4.031780x)
+ exp_size (4.619188x)

As you can see, mod_size (len("%i" % i)) is the fastest, slightly faster than using str(i) and significantly faster than others.

Python 2.* ints take either 4 or 8 bytes (32 or 64 bits), depending on your Python build. sys.maxint (2**31-1 for 32-bit ints, 2**63-1 for 64-bit ints) will tell you which of the two possibilities obtains.

In Python 3, ints (like longs in Python 2) can take arbitrary sizes up to the amount of available memory; sys.getsizeof gives you a good indication for any given value, although it does also count some fixed overhead:

>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28

If, as other answers suggests, you're thinking about some string representation of the integer value, then just take the len of that representation, be it in base 10 or otherwise!

Count the number of digits w/o convert integer to a string:

x=123
x=abs(x)
i = 0
while x >= 10**i:
    i +=1
# i is the number of digits

Here is a bulky but fast version :

def nbdigit ( x ):
    if x >= 10000000000000000 : # 17 -
        return len( str( x ))
    if x < 100000000 : # 1 - 8
        if x < 10000 : # 1 - 4
            if x < 100             : return (x >= 10)+1 
            else                   : return (x >= 1000)+3
        else: # 5 - 8                                                 
            if x < 1000000         : return (x >= 100000)+5 
            else                   : return (x >= 10000000)+7
    else: # 9 - 16 
        if x < 1000000000000 : # 9 - 12
            if x < 10000000000     : return (x >= 1000000000)+9 
            else                   : return (x >= 100000000000)+11
        else: # 13 - 16
            if x < 100000000000000 : return (x >= 10000000000000)+13 
            else                   : return (x >= 1000000000000000)+15

Only 5 comparisons for not too big numbers. On my computer it is about 30% faster than the math.log10 version and 5% faster than the len( str()) one. Ok... no so attractive if you don't use it furiously.

And here is the set of numbers I used to test/measure my function:

n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]

NB: it does not manage negative numbers, but the adaptation is easy...

Assuming you are asking for the largest number you can store in an integer, the value is implementation dependent. I suggest that you don't think in that way when using python. In any case, quite a large value can be stored in a python 'integer'. Remember, Python uses duck typing!

Edit: I gave my answer before the clarification that the asker wanted the number of digits. For that, I agree with the method suggested by the accepted answer. Nothing more to add!

def length(i):
  return len(str(i))

It can be done for integers quickly by using:

len(str(abs(1234567890)))

Which gets the length of the string of the absolute value of "1234567890"

abs returns the number WITHOUT any negatives (only the magnitude of the number), str casts/converts it to a string and len returns the string length of that string.

If you want it to work for floats, you can use either of the following:

# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])

# Ignore just the decimal place
len(str(abs(0.1234567890)))-1

For future reference.

def count_digit(number):
  if number >= 10:
    count = 2
  else:
    count = 1
  while number//10 > 9:
    count += 1
    number = number//10
  return count
def digits(n)
    count = 0
    if n == 0:
        return 1
    
    if n < 0:
        n *= -1

    while (n >= 10**count):
        count += 1
        n += n%10

    return count

print(digits(25))   # Should print 2
print(digits(144))  # Should print 3
print(digits(1000)) # Should print 4
print(digits(0))    # Should print 1

Here is another way to compute the number of digit before the decimal of any number

from math import fabs

len(format(fabs(100),".0f"))
Out[102]: 3

len(format(fabs(1e10),".0f"))
Out[165]: 11

len(format(fabs(1235.4576),".0f"))
Out[166]: 4

I did a brief benchmark test, for 10,000 loops

num     len(str(num))     ----  len(format(fabs(num),".0f")) ---- speed-up
2**1e0  2.179400e-07 sec  ----     8.577000e-07 sec          ---- 0.2541
2**1e1  2.396900e-07 sec  ----     8.668800e-07 sec          ---- 0.2765
2**1e2  9.587700e-07 sec  ----     1.330370e-06 sec          ---- 0.7207
2**1e3  2.321700e-06 sec  ----     1.761305e-05 sec          ---- 0.1318

It is slower but a simpler option.

But even this solution does give wrong results from 9999999999999998

len(format(fabs(9999999999999998),".0f"))
Out[146]: 16
len(format(fabs(9999999999999999),".0f"))
Out[145]: 17

If you have to ask an user to give input and then you have to count how many numbers are there then you can follow this:

count_number = input('Please enter a number\t')

print(len(count_number))

Note: Never take an int as user input.

My code for the same is as follows;i have used the log10 method:

from math import *

def digit_count(number):

if number>1 and round(log10(number))>=log10(number) and number%10!=0 :
    return round(log10(number))
elif  number>1 and round(log10(number))<log10(number) and number%10!=0:
    return round(log10(number))+1
elif number%10==0 and number!=0:
    return int(log10(number)+1)
elif number==1 or number==0:
    return 1

I had to specify in case of 1 and 0 because log10(1)=0 and log10(0)=ND and hence the condition mentioned isn't satisfied. However, this code works only for whole numbers.

Top answers are saying mathlog10 faster but I got results that suggest len(str(n)) is faster.

arr = []
for i in range(5000000):
    arr.append(random.randint(0,12345678901234567890))
%%timeit

for n in arr:
    len(str(n))
//2.72 s ± 304 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit

for n in arr:
    int(math.log10(n))+1
//3.13 s ± 545 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Besides, I haven't added logic to the math way to return accurate results and I can only imagine it slows it even more.

I have no idea how the previous answers proved the maths way is faster though.

n = 3566002020360505
count = 0
while(n>0):
  count += 1
  n = n //10
print(f"The number of digits in the number are: {count}")

output: The number of digits in the number are: 16

If you are looking for a solution without using inbuilt functions. Only caveat is when you send a = 000.

def number_length(a: int) -> int:
    length = 0
    if a == 0:
        return length + 1
    else:
        while a > 0:
            a = a // 10
            length += 1
        return length
    

if __name__ == '__main__':
    print(number_length(123)
    assert number_length(10) == 2
    assert number_length(0) == 1
    assert number_length(256) == 3
    assert number_length(4444) == 4

A fast solution that uses a self-correcting implementation of floor(log10(n)) based on "Better way to compute floor of log(n,b) for integers n and b?".

import math

def floor_log(n, b):
    res = math.floor(math.log(n, b))
    c = b**res
    return res + (b*c <= n) - (c > n)

def num_digits(n):
    return 1 if n == 0 else 1 + floor_log(abs(n), 10)

This is quite fast and will work whenever n < 10**(2**52) (which is really really big).

Here is the simplest approach without need to be convert int into the string:

suppose a number of 15 digits is given eg; n=787878899999999;

n=787878899999999 
n=abs(n) // we are finding absolute value because if the number is negative int to string conversion will produce wrong output

count=0 //we have taken a counter variable which will increment itself till the last digit

while(n):
    n=n//10   /*Here we are removing the last digit of a number...it will remove until 0 digits will left...and we know that while(0) is False*/
    count+=1  /*this counter variable simply increase its value by 1 after deleting a digit from the original number
print(count)   /*when the while loop will become False because n=0, we will simply print the value of counter variable

Input :

n=787878899999999

Output:

15

Solution without imports and functions like str()

def numlen(num):
    result = 1
    divider = 10
    while num % divider != num:
        divider *= 10
        result += 1
    return result

you can use it like this,

n = -123.123
digits = len(str(abs(int(n))))
print(digits)

digitswithdecimals = len(str(abs(n)))-1
print(digitswithdecimals)

OUTPUT:

3

6

Explanation :

int(n) - strips any decimal number from the number

::: -123.123 >> -123

<. . . . . . . . . . . . . #to include decimal points we will remove this part and subtracts by 1 to get exclude the point '.' >

abs(int(n)) - strips negative from the previous result ,if any

::: -123 >> 123

str(abs(int(n))) - convert the previous result to string

::: 123 >> '123'

len(str(abs(int(n)))) - return the length of the string

::: length('123') = 3

coin_digit = str(coin_fark).split(".")[1]
coin_digit_len = len(coin_digit)
print(coin_digit_len)
>>> a=12345
>>> a.__str__().__len__()
5
Related