0

I am trying to write a function that counts the number of digits in a given number. This is my function:

def num_digits(n):
    """
    >>> num_digits(12345)
    5
    >>> num_digits(0)
    1
    >>> num_digits(-12345)
    5
    """
    count = 0
    while n > 0:
        if n == 0:
            count += 1
        count += 1
        n = n/10

    return count

if __name__=="__main__":
    import doctest
    doctest.testmod(verbose=True)

But this function is not working. What should the condition be for the while loop?

codingwarrior
  • 107
  • 2
  • 4
  • 11
  • 2
    Your responsibility as a question is to give meaningful and precise question. You haven't even tell how your function "is not working". Anyway, a hint for you: Your function is supposed to handle negative number, but your while loop checks for n > 0 ... which means... – Adrian Shum Mar 26 '14 at 10:34
  • @AdrianShum the program as given has built in doc tests and running it shows exactly which input data doesn't work. So I disagree that it is not a "meaningful and precise question". IMHO it's a whole lot better than many! – Vorsprung Mar 26 '14 at 12:36
  • 1
    @Vorsprung well... there are always worse questions. However, there are worse question doesn't mean this one is good enough. What I can see here is something that a normal developer should be able to find the cause (negative number / 10 is not giving result as expected). Then the question should be something more precise: How should negative integer division be handled in python – Adrian Shum Mar 27 '14 at 01:33
  • @adrianShum You should be able to read a program without someone explaining it to you. Thats why i put the doctest there. – codingwarrior Mar 29 '14 at 22:13
  • @codingwarrior Of course I can and that's why in my comment I have pointed out the problem. However, even we have ability to read the program, it doesn't mean we should spend our time dealing with something that the questioners are obligated to solve by themselves. PERIOD. – Adrian Shum Mar 31 '14 at 02:54

11 Answers11

16

Here's a a defined method:

def numLen(num):
  return len(str(abs(num)))
NooBskie
  • 3,571
  • 25
  • 49
Karanja Denis
  • 328
  • 3
  • 8
  • 1
    This is considerably slower than the classical solution which involves continuously dividing by `10`. This solution involves constructing a new string instance which has overhead costs. – Hatefiend Jan 18 '20 at 14:30
  • This does also count `.` as dig. So this will produce wrong results sometimes. As example for floats. – Lukas1818 May 17 '22 at 14:05
8
from math import log, ceil
print(int(ceil(log(number+1, 10))))

log() returns approximate value, so 1 need to be added. ceil() is used because we need whole numbers

Shedokan
  • 1,142
  • 1
  • 9
  • 21
Miae Kim
  • 1,571
  • 18
  • 24
2

Python2 implementation

def numDigits(n): 
    return len(filter(lambda m:m.isdigit(), str(n)))

For Python3, the filter command returns an iterator. Hence, you must do:

def numDigits(n): 
    return len(list(filter(lambda m:m.isdigit(), str(n))))

Not sure why we would need a while implementation, but it is possible...

count = 0
while len(string) > 0:
    if string[0].isdigit(): count += 1
    string = string[1:]

print(count)
ssm
  • 5,105
  • 1
  • 21
  • 39
  • Is it possible with a while loop? – codingwarrior Mar 26 '14 at 09:26
  • This works for me if I put the filter inside a list: `def numDigits(n): return len(list(filter(lambda m:m.isdigit(), str(n))))` – jss367 Aug 21 '17 at 12:45
  • Note: There is no need for a `lambda` here. `filter(str.isdigit, str(n))` would work just fine, and more efficiently (if you need a `lambda` to use `filter`, an equivalent listcomp/genexpr is generally faster, but in this case, you can pass a built-in function to eke out a little extra speed). – ShadowRanger Aug 23 '17 at 03:11
  • @ShadowRanger: Yes, very correct. Thanks for catching that – ssm Aug 23 '17 at 05:01
2

Here is the answer:

def num_digits(n):
    """
    >>> num_digits(12345)
    5
    >>> num_digits(0)
    1
    >>> num_digits(-12345)
    5
    """
    count = 0
    if n == 0:
        return 1
    
    if n < 0:
        n *= -1

    while n != 0:
        count += 1
        n = n // 10

    return count

if __name__=="__main__":
    import doctest
    doctest.testmod(verbose=True)
vsminkov
  • 10,252
  • 2
  • 36
  • 49
codingwarrior
  • 107
  • 2
  • 4
  • 11
2
def numDigits(n):
    n_str = str(n)
    return len(n_str)

num = input("Enter a digit")
print("The number of digits is:", numDigits(num)) 
Mallan627
  • 21
  • 3
  • This response was from a year ago, but perhaps someone can answer: For calculations (eg determining whether `n` is rounded up or down), does this code make sense, since it turns the number `n` to a string? – YCode Jan 05 '18 at 03:28
1

There's obviously a bug in the code, so please think about it a bit harder.

while n > 0:
    if n == 0:

How can n == 0 ever be true if we just checked that n > 0?

Nicolas Louis Guillemot
  • 1,542
  • 1
  • 10
  • 22
1

You could do this instead

  def num_digits(a):
      return len(repr(abs(n)))
Vorsprung
  • 30,988
  • 4
  • 36
  • 58
  • Is it possible with a while loop? – codingwarrior Mar 26 '14 at 09:27
  • 1
    python has functions like ``repr``, ``abs`` and ``len`` to avoid having to rewrite basic features using control structures like while loops. The use of doctests in your example is great btw – Vorsprung Mar 26 '14 at 09:30
  • thanks but you did not answer the question.? – codingwarrior Mar 26 '14 at 09:40
  • 1
    I did answer the question! The functions I've used might internally (maybe in the C code underlying python) use things like while loops. But the functions used consider the number as a whole thing without any need for repeated operations. Just to make it crystal clear- using this functional method there is no need for any loop and it's hard to see how adding a while loop to the method would work at all – Vorsprung Mar 26 '14 at 09:54
0

This works. However, I prefer my other answer above

def num_digits(n):
    n = abs(n)
    count = 1
    while (int(n/10)) > 0:
        count += 1
        n=int(n/10)
    return count
Vorsprung
  • 30,988
  • 4
  • 36
  • 58
0

Here is my code. A slightly modified version of Vorsprung

def num_digits(n):
    count = 1
    while (int(n/10)) is not 0:
        count += 1
        n = int(n/10)
    return count

The basic difference is that no abs() is needed

As a note (for integer input) this is a Python3 ansatz since the devision is a 'true' one and not a 'classic' C-like one like in Python2. This means that the devision of two integers is a float (1/2 = 0.5) and not an integer (1/2 = 0). Hence in Python2 the conversion to an int in the line n = int(n/10) is not necessary for integer input.

This function might not rely on python basic functions/features like len(repr(abs(n))) but has the advantage that it also works with large floats like for example 1.23e19

Daniel
  • 143
  • 1
  • 10
0
def num_digits(s):
   o = sum(c.isdigit() for c in s)
   return o

There is s = "asda234asdasd23" and return you get 5.

or sort version:

num_digits = lambda s: sum('/' < c < ':' for c in s)

where s is a string!

DavidS
  • 278
  • 1
  • 17
0

You can do it by looping it as a string and only add to the counter when the character belongs to a list of possible digits.

text_input = input("Please enter the input")
count = 0
for i in text_input:
    if i in '0,1,2,3,4,5,6,7,8,9':
        count = count + 1

print("Count is:", count)
armatita
  • 11,531
  • 8
  • 49
  • 48
  • Notice that when you ask if `i` is in the `'0,1,2,3,4,5,6,7,8,9'` string the `,` will also count as valid digit. Perhaps something like this `'0123456789'` would be better. Also try to provide context to your code answers. Yours, although valid, was in the low-quality list for reviewing (moderation tool in SO). – armatita May 08 '16 at 16:04