Skip to content

Commit 19c3871

Browse files
Added function to convert from decimal to another base (TheAlgorithms#2087)
* Added function to convert from decimal to another base * Update conversions/decimal_to_any.py Changed type() to isinstance() Co-authored-by: Christian Clauss <cclauss@me.com> * Update conversions/decimal_to_any.py Changed to base in (0, 1) Co-authored-by: Christian Clauss <cclauss@me.com> * Update conversions/decimal_to_any.py Updated to div not in (0, 1) Co-authored-by: Christian Clauss <cclauss@me.com> * Update conversions/decimal_to_any.py Updated to make condition clearer Co-authored-by: Christian Clauss <cclauss@me.com> * Update conversions/decimal_to_any.py Using divmod() instead of % operator Co-authored-by: Christian Clauss <cclauss@me.com> * Update conversions/decimal_to_any.py Improved readability on a docstring test Co-authored-by: Christian Clauss <cclauss@me.com> * Update conversions/decimal_to_any.py Changed use of type() to isinstance() Co-authored-by: Christian Clauss <cclauss@me.com> * Update conversions/decimal_to_any.py Changed from use of type() to isinstance() Co-authored-by: Christian Clauss <cclauss@me.com> * Made changes and improved function * Update conversions/decimal_to_any.py Added space to docstring test Co-authored-by: Christian Clauss <cclauss@me.com> * Changed action for bad input * Added support for conversions up to base 36 (TheAlgorithms#2087) * Added support for conversions up to base 36 and renamed HEXADECIMAL dict (TheAlgorithms#2087) * Fixed whitespace issue (TheAlgorithms#2087) * Fixed issue with line length (TheAlgorithms#2087) * Fixed issue with conversions past base-10 failing (TheAlgorithms#2087) * Added more robust testing (TheAlgorithms#2087) Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent a7b4311 commit 19c3871

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

‎conversions/decimal_to_any.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""Convert a positive Decimal Number to Any Other Representation"""
2+
3+
4+
def decimal_to_any(num: int, base: int) -> str:
5+
6+
"""
7+
Convert a positive integer to another base as str.
8+
>>> decimal_to_any(0, 2)
9+
'0'
10+
>>> decimal_to_any(5, 4)
11+
'11'
12+
>>> decimal_to_any(20, 3)
13+
'202'
14+
>>> decimal_to_any(58, 16)
15+
'3A'
16+
>>> decimal_to_any(243, 17)
17+
'E5'
18+
>>> decimal_to_any(34923, 36)
19+
'QY3'
20+
>>> decimal_to_any(10, 11)
21+
'A'
22+
>>> decimal_to_any(16, 16)
23+
'10'
24+
>>> decimal_to_any(36, 36)
25+
'10'
26+
>>> # negatives will error
27+
>>> decimal_to_any(-45, 8) # doctest: +ELLIPSIS
28+
Traceback (most recent call last):
29+
...
30+
ValueError: parameter must be positive int
31+
>>> # floats will error
32+
>>> decimal_to_any(34.4, 6) # doctest: +ELLIPSIS
33+
Traceback (most recent call last):
34+
...
35+
TypeError: int() can't convert non-string with explicit base
36+
>>> # a float base will error
37+
>>> decimal_to_any(5, 2.5) # doctest: +ELLIPSIS
38+
Traceback (most recent call last):
39+
...
40+
TypeError: 'float' object cannot be interpreted as an integer
41+
>>> # a str base will error
42+
>>> decimal_to_any(10, '16') # doctest: +ELLIPSIS
43+
Traceback (most recent call last):
44+
...
45+
TypeError: 'str' object cannot be interpreted as an integer
46+
>>> # a base less than 2 will error
47+
>>> decimal_to_any(7, 0) # doctest: +ELLIPSIS
48+
Traceback (most recent call last):
49+
...
50+
ValueError: base must be >= 2
51+
>>> # a base greater than 36 will error
52+
>>> decimal_to_any(34, 37) # doctest: +ELLIPSIS
53+
Traceback (most recent call last):
54+
...
55+
ValueError: base must be <= 36
56+
"""
57+
if isinstance(num, float):
58+
raise TypeError("int() can't convert non-string with explicit base")
59+
if num < 0:
60+
raise ValueError("parameter must be positive int")
61+
if isinstance(base, str):
62+
raise TypeError("'str' object cannot be interpreted as an integer")
63+
if isinstance(base, float):
64+
raise TypeError("'float' object cannot be interpreted as an integer")
65+
if base in (0, 1):
66+
raise ValueError("base must be >= 2")
67+
if base > 36:
68+
raise ValueError("base must be <= 36")
69+
70+
ALPHABET_VALUES = {'10': 'A', '11': 'B', '12': 'C', '13': 'D', '14': 'E', '15': 'F', '16': 'G', '17': 'H',
71+
'18': 'I', '19': 'J', '20': 'K', '21': 'L', '22': 'M', '23': 'N', '24': 'O', '25': 'P',
72+
'26': 'Q', '27': 'R', '28': 'S', '29': 'T', '30': 'U', '31': 'V', '32': 'W', '33': 'X',
73+
'34': 'Y', '35': 'Z'}
74+
new_value = ""
75+
mod = 0
76+
div = 0
77+
while div != 1:
78+
div, mod = divmod(num, base)
79+
if base >= 11 and 9 < mod < 36:
80+
actual_value = ALPHABET_VALUES[str(mod)]
81+
mod = actual_value
82+
new_value += str(mod)
83+
div = num // base
84+
num = div
85+
if div == 0:
86+
return str(new_value[::-1])
87+
elif div == 1:
88+
new_value += str(div)
89+
return str(new_value[::-1])
90+
91+
return new_value[::-1]
92+
93+
94+
if __name__ == "__main__":
95+
import doctest
96+
97+
doctest.testmod()
98+
99+
for base in range(2, 37):
100+
for num in range(1000):
101+
assert int(decimal_to_any(num, base), base) == num, (
102+
num, base, decimal_to_any(num, base),
103+
int(decimal_to_any(num, base), base)
104+
)

0 commit comments

Comments
 (0)