Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
</a>

<!-- Short description: -->
<h3>All algorithms implemented in Python - for education 📚</h3>
<h3>All algorithms implemented in Python - for educational purposes 📚</h3>
</div>

Implementations are for learning purposes only. They may be less efficient than the implementations in the Python standard library. Use them at your discretion.
Expand Down
37 changes: 18 additions & 19 deletions maths/number_of_digits.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import math
from timeit import timeit
from typing import Callable

Check failure on line 3 in maths/number_of_digits.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (UP035)

maths/number_of_digits.py:3:1: UP035 Import from `collections.abc` instead: `Callable`


def num_digits(n: int) -> int:
"""
Find the number of digits in a number.
Find the number of digits in an integer.

>>> num_digits(12345)
5
Expand All @@ -21,7 +22,6 @@
...
TypeError: Input must be an integer
"""

if not isinstance(n, int):
raise TypeError("Input must be an integer")

Expand All @@ -37,8 +37,7 @@

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.
Find the number of digits using logarithm.

>>> num_digits_fast(12345)
5
Expand All @@ -50,22 +49,19 @@
1
>>> num_digits_fast(-123456)
6
>>> num_digits('123') # Raises a TypeError for non-integer input
>>> num_digits_fast('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)
return 1 if n == 0 else math.floor(math.log10(abs(n)) + 1)


def num_digits_faster(n: int) -> int:
"""
Find the number of digits in a number.
abs() is used for negative numbers
Find the number of digits using string conversion.

>>> num_digits_faster(12345)
5
Expand All @@ -77,30 +73,32 @@
1
>>> num_digits_faster(-123456)
6
>>> num_digits('123') # Raises a TypeError for non-integer input
>>> num_digits_faster('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.
Benchmark multiple functions with three different length integers.
"""
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")
timing = timeit(f"__main__.{call}", setup="import __main__", number=10000)
print(f"{call}: Result={func(value)}, Time={timing:.6f} sec")

for value in (262144, 1125899906842624, 1267650600228229401496703205376):
test_values = [
262144,
1125899906842624,
1267650600228229401496703205376,
]

for value in test_values:
for func in (num_digits, num_digits_fast, num_digits_faster):
benchmark_a_function(func, value)
print()
Expand All @@ -111,3 +109,4 @@

doctest.testmod()
benchmark()

Loading