Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 06edc0e

Browse files
tianyizheng02github-actions
and
github-actions
authored
Consolidate binary exponentiation files (TheAlgorithms#10742)
* Consolidate binary exponentiation files * updating DIRECTORY.md * Fix typos in doctests * Add suggestions from code review * Fix timeit benchmarks --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
1 parent 47c19d9 commit 06edc0e

File tree

4 files changed

+181
-124
lines changed

4 files changed

+181
-124
lines changed

‎DIRECTORY.md‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,9 +578,7 @@
578578
* [Bailey Borwein Plouffe](maths/bailey_borwein_plouffe.py)
579579
* [Base Neg2 Conversion](maths/base_neg2_conversion.py)
580580
* [Basic Maths](maths/basic_maths.py)
581-
* [Binary Exp Mod](maths/binary_exp_mod.py)
582581
* [Binary Exponentiation](maths/binary_exponentiation.py)
583-
* [Binary Exponentiation 2](maths/binary_exponentiation_2.py)
584582
* [Binary Multiplication](maths/binary_multiplication.py)
585583
* [Binomial Coefficient](maths/binomial_coefficient.py)
586584
* [Binomial Distribution](maths/binomial_distribution.py)

‎maths/binary_exp_mod.py‎

Lines changed: 0 additions & 28 deletions
This file was deleted.

‎maths/binary_exponentiation.py‎

Lines changed: 181 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,196 @@
1-
"""Binary Exponentiation."""
1+
"""
2+
Binary Exponentiation
23
3-
# Author : Junth Basnet
4-
# Time Complexity : O(logn)
4+
This is a method to find a^b in O(log b) time complexity and is one of the most commonly
5+
used methods of exponentiation. The method is also useful for modular exponentiation,
6+
when the solution to (a^b) % c is required.
57
8+
To calculate a^b:
9+
- If b is even, then a^b = (a * a)^(b / 2)
10+
- If b is odd, then a^b = a * a^(b - 1)
11+
Repeat until b = 1 or b = 0
612
7-
def binary_exponentiation(a: int, n: int) -> int:
13+
For modular exponentiation, we use the fact that (a * b) % c = ((a % c) * (b % c)) % c
14+
"""
15+
16+
17+
def binary_exp_recursive(base: float, exponent: int) -> float:
818
"""
9-
Compute a number raised by some quantity
10-
>>> binary_exponentiation(-1, 3)
19+
Computes a^b recursively, where a is the base and b is the exponent
20+
21+
>>> binary_exp_recursive(3, 5)
22+
243
23+
>>> binary_exp_recursive(11, 13)
24+
34522712143931
25+
>>> binary_exp_recursive(-1, 3)
1126
-1
12-
>>> binary_exponentiation(-1, 4)
27+
>>> binary_exp_recursive(0, 5)
28+
0
29+
>>> binary_exp_recursive(3, 1)
30+
3
31+
>>> binary_exp_recursive(3, 0)
1332
1
14-
>>> binary_exponentiation(2, 2)
15-
4
16-
>>> binary_exponentiation(3, 5)
33+
>>> binary_exp_recursive(1.5, 4)
34+
5.0625
35+
>>> binary_exp_recursive(3, -1)
36+
Traceback (most recent call last):
37+
...
38+
ValueError: Exponent must be a non-negative integer
39+
"""
40+
if exponent < 0:
41+
raise ValueError("Exponent must be a non-negative integer")
42+
43+
if exponent == 0:
44+
return 1
45+
46+
if exponent % 2 == 1:
47+
return binary_exp_recursive(base, exponent - 1) * base
48+
49+
b = binary_exp_recursive(base, exponent // 2)
50+
return b * b
51+
52+
53+
def binary_exp_iterative(base: float, exponent: int) -> float:
54+
"""
55+
Computes a^b iteratively, where a is the base and b is the exponent
56+
57+
>>> binary_exp_iterative(3, 5)
1758
243
18-
>>> binary_exponentiation(10, 3)
19-
1000
20-
>>> binary_exponentiation(5e3, 1)
21-
5000.0
22-
>>> binary_exponentiation(-5e3, 1)
23-
-5000.0
24-
"""
25-
if n == 0:
59+
>>> binary_exp_iterative(11, 13)
60+
34522712143931
61+
>>> binary_exp_iterative(-1, 3)
62+
-1
63+
>>> binary_exp_iterative(0, 5)
64+
0
65+
>>> binary_exp_iterative(3, 1)
66+
3
67+
>>> binary_exp_iterative(3, 0)
68+
1
69+
>>> binary_exp_iterative(1.5, 4)
70+
5.0625
71+
>>> binary_exp_iterative(3, -1)
72+
Traceback (most recent call last):
73+
...
74+
ValueError: Exponent must be a non-negative integer
75+
"""
76+
if exponent < 0:
77+
raise ValueError("Exponent must be a non-negative integer")
78+
79+
res: int | float = 1
80+
while exponent > 0:
81+
if exponent & 1:
82+
res *= base
83+
84+
base *= base
85+
exponent >>= 1
86+
87+
return res
88+
89+
90+
def binary_exp_mod_recursive(base: float, exponent: int, modulus: int) -> float:
91+
"""
92+
Computes a^b % c recursively, where a is the base, b is the exponent, and c is the
93+
modulus
94+
95+
>>> binary_exp_mod_recursive(3, 4, 5)
96+
1
97+
>>> binary_exp_mod_recursive(11, 13, 7)
98+
4
99+
>>> binary_exp_mod_recursive(1.5, 4, 3)
100+
2.0625
101+
>>> binary_exp_mod_recursive(7, -1, 10)
102+
Traceback (most recent call last):
103+
...
104+
ValueError: Exponent must be a non-negative integer
105+
>>> binary_exp_mod_recursive(7, 13, 0)
106+
Traceback (most recent call last):
107+
...
108+
ValueError: Modulus must be a positive integer
109+
"""
110+
if exponent < 0:
111+
raise ValueError("Exponent must be a non-negative integer")
112+
if modulus <= 0:
113+
raise ValueError("Modulus must be a positive integer")
114+
115+
if exponent == 0:
26116
return 1
27117

28-
elifn % 2 == 1:
29-
return binary_exponentiation(a, n - 1) * a
118+
ifexponent % 2 == 1:
119+
return (binary_exp_mod_recursive(base, exponent - 1, modulus) * base) %modulus
30120

31-
else:
32-
b = binary_exponentiation(a, n // 2)
33-
return b * b
121+
r = binary_exp_mod_recursive(base, exponent // 2, modulus)
122+
return (r * r) % modulus
34123

35124

36-
if __name__ == "__main__":
37-
import doctest
125+
def binary_exp_mod_iterative(base: float, exponent: int, modulus: int) -> float:
126+
"""
127+
Computes a^b % c iteratively, where a is the base, b is the exponent, and c is the
128+
modulus
38129
39-
doctest.testmod()
130+
>>> binary_exp_mod_iterative(3, 4, 5)
131+
1
132+
>>> binary_exp_mod_iterative(11, 13, 7)
133+
4
134+
>>> binary_exp_mod_iterative(1.5, 4, 3)
135+
2.0625
136+
>>> binary_exp_mod_iterative(7, -1, 10)
137+
Traceback (most recent call last):
138+
...
139+
ValueError: Exponent must be a non-negative integer
140+
>>> binary_exp_mod_iterative(7, 13, 0)
141+
Traceback (most recent call last):
142+
...
143+
ValueError: Modulus must be a positive integer
144+
"""
145+
if exponent < 0:
146+
raise ValueError("Exponent must be a non-negative integer")
147+
if modulus <= 0:
148+
raise ValueError("Modulus must be a positive integer")
149+
150+
res: int | float = 1
151+
while exponent > 0:
152+
if exponent & 1:
153+
res = ((res % modulus) * (base % modulus)) % modulus
154+
155+
base *= base
156+
exponent >>= 1
157+
158+
return res
159+
160+
161+
if __name__ == "__main__":
162+
from timeit import timeit
40163

41-
try:
42-
BASE = int(float(input("Enter Base : ").strip()))
43-
POWER = int(input("Enter Power : ").strip())
44-
except ValueError:
45-
print("Invalid literal for integer")
164+
a = 1269380576
165+
b = 374
166+
c = 34
46167

47-
RESULT = binary_exponentiation(BASE, POWER)
48-
print(f"{BASE}^({POWER}) : {RESULT}")
168+
runs = 100_000
169+
print(
170+
timeit(
171+
f"binary_exp_recursive({a}, {b})",
172+
setup="from __main__ import binary_exp_recursive",
173+
number=runs,
174+
)
175+
)
176+
print(
177+
timeit(
178+
f"binary_exp_iterative({a}, {b})",
179+
setup="from __main__ import binary_exp_iterative",
180+
number=runs,
181+
)
182+
)
183+
print(
184+
timeit(
185+
f"binary_exp_mod_recursive({a}, {b}, {c})",
186+
setup="from __main__ import binary_exp_mod_recursive",
187+
number=runs,
188+
)
189+
)
190+
print(
191+
timeit(
192+
f"binary_exp_mod_iterative({a}, {b}, {c})",
193+
setup="from __main__ import binary_exp_mod_iterative",
194+
number=runs,
195+
)
196+
)

‎maths/binary_exponentiation_2.py‎

Lines changed: 0 additions & 61 deletions
This file was deleted.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /