Repository: TheAlgorithms/Python

Issue:
maths/number_of_digits.py is naive!
<code>[maths/number_of_digits.py](https://github.com/TheAlgorithms/Python/blob/master/maths/number_of_digits.py)</code> has a naive method. The suggested method has a time complexity of O(n). We can count number of digits of a number in O(1).


Discussion:

Resolving patch:
diff --git a/maths/number_of_digits.py b/maths/number_of_digits.py
--- a/maths/number_of_digits.py
+++ b/maths/number_of_digits.py
@@ -1,3 +1,7 @@
+import math
+from timeit import timeit
+
+
 def num_digits(n: int) -> int:
     """
     Find the number of digits in a number.
@@ -14,5 +18,82 @@ def num_digits(n: int) -> int:
     return digits
 
 
+def num_digits_fast(n: int) -> int:
+    """
+    Find the number of digits in a number.
+    abs() is used as logarithm for negative numbers is not defined.
+
+    >>> num_digits_fast(12345)
+    5
+    >>> num_digits_fast(123)
+    3
+    """
+    return (math.floor(math.log(abs(n), 10) + 1))
+
+
+def num_digits_faster(n: int) -> int:
+    """
+    Find the number of digits in a number.
+    abs() is used for negative numbers
+
+    >>> num_digits_faster(12345)
+    5
+    >>> num_digits_faster(123)
+    3
+    """
+    return (len(str(abs(n))))
+
+
+def benchmark() -> None:
+    """
+    Benchmark code for comparing 3 functions,
+    with 3 different length int values.
+    """
+    print('\nFor small_num = ', small_num, ':')
+    print("> num_digits()",
+          '\t\tans =', num_digits(small_num),
+          '\ttime =', timeit("z.num_digits(z.small_num)",
+                             setup="import __main__ as z"), "seconds")
+    print("> num_digits_fast()",
+          '\tans =', num_digits_fast(small_num),
+          '\ttime =', timeit("z.num_digits_fast(z.small_num)",
+                             setup="import __main__ as z"), "seconds")
+    print("> num_digits_faster()",
+          '\tans =', num_digits_faster(small_num),
+          '\ttime =', timeit("z.num_digits_faster(z.small_num)",
+                             setup="import __main__ as z"), "seconds")
+
+    print('\nFor medium_num = ', medium_num, ':')
+    print("> num_digits()",
+          '\t\tans =', num_digits(medium_num),
+          '\ttime =', timeit("z.num_digits(z.medium_num)",
+                             setup="import __main__ as z"), "seconds")
+    print("> num_digits_fast()",
+          '\tans =', num_digits_fast(medium_num),
+          '\ttime =', timeit("z.num_digits_fast(z.medium_num)",
+                             setup="import __main__ as z"), "seconds")
+    print("> num_digits_faster()",
+          '\tans =', num_digits_faster(medium_num),
+          '\ttime =', timeit("z.num_digits_faster(z.medium_num)",
+                             setup="import __main__ as z"), "seconds")
+
+    print('\nFor large_num = ', large_num, ':')
+    print("> num_digits()",
+          '\t\tans =', num_digits(large_num),
+          '\ttime =', timeit("z.num_digits(z.large_num)",
+                             setup="import __main__ as z"), "seconds")
+    print("> num_digits_fast()",
+          '\tans =', num_digits_fast(large_num),
+          '\ttime =', timeit("z.num_digits_fast(z.large_num)",
+                             setup="import __main__ as z"), "seconds")
+    print("> num_digits_faster()",
+          '\tans =', num_digits_faster(large_num),
+          '\ttime =', timeit("z.num_digits_faster(z.large_num)",
+                             setup="import __main__ as z"), "seconds")
+
+
 if __name__ == "__main__":
-    print(num_digits(12345))  # ===> 5
+    small_num = 262144
+    medium_num = 1125899906842624
+    large_num = 1267650600228229401496703205376
+    benchmark()


Test patch: