forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
number_of_digits.py
113 lines (91 loc) · 2.56 KB
/
number_of_digits.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import math
from timeit import timeit
def num_digits(n: int) -> int:
"""
Find the number of digits in a number.
>>> num_digits(12345)
5
>>> num_digits(123)
3
>>> num_digits(0)
1
>>> num_digits(-1)
1
>>> num_digits(-123456)
6
>>> num_digits('123') # Raises a TypeError for non-integer input
Traceback (most recent call last):
...
TypeError: Input must be an integer
"""
if not isinstance(n, int):
raise TypeError("Input must be an integer")
digits = 0
n = abs(n)
while True:
n = n // 10
digits += 1
if n == 0:
break
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
>>> num_digits_fast(0)
1
>>> num_digits_fast(-1)
1
>>> num_digits_fast(-123456)
6
>>> num_digits('123') # Raises a TypeError for non-integer input
Traceback (most recent call last):
...
TypeError: Input must be an integer
"""
if not isinstance(n, int):
raise TypeError("Input must be an integer")
return 1 if n == 0 else 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
>>> num_digits_faster(0)
1
>>> num_digits_faster(-1)
1
>>> num_digits_faster(-123456)
6
>>> num_digits('123') # Raises a TypeError for non-integer input
Traceback (most recent call last):
...
TypeError: Input must be an integer
"""
if not isinstance(n, int):
raise TypeError("Input must be an integer")
return len(str(abs(n)))
def benchmark() -> None:
"""
Benchmark multiple functions, with three different length int values.
"""
from collections.abc import Callable
def benchmark_a_function(func: Callable, value: int) -> None:
call = f"{func.__name__}({value})"
timing = timeit(f"__main__.{call}", setup="import __main__")
print(f"{call}: {func(value)} -- {timing} seconds")
for value in (262144, 1125899906842624, 1267650600228229401496703205376):
for func in (num_digits, num_digits_fast, num_digits_faster):
benchmark_a_function(func, value)
print()
if __name__ == "__main__":
import doctest
doctest.testmod()
benchmark()