Advertisement
drinfernoo

Untitled

Sep 29th, 2023
680
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.43 KB | None | 0 0
  1. import sys
  2.  
  3.  
  4. BASE_LABELS = {
  5.     2: "Binary",
  6.     3: "Ternary",
  7.     4: "Quaternary",
  8.     5: "Quinary",
  9.     6: "Senary",
  10.     7: "Septenary",
  11.     8: "Octal",
  12.     9: "Nonary",
  13.     10: "Decimal",
  14.     11: "Undecimal",
  15.     12: "Duodecimal",
  16.     13: "Tridecimal",
  17.     14: "Tetradecimal",
  18.     15: "Pentadecimal",
  19.     16: "Hexadecimal",
  20. }
  21. DIGIT_VALUES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  22.  
  23.  
  24. def char_to_value(char: str) -> int:
  25.     return DIGIT_VALUES.index(char.upper())
  26.  
  27.  
  28. def value_to_char(value: int) -> str:
  29.     return DIGIT_VALUES[value]
  30.  
  31.  
  32. def is_valid_number(number: str, base: int) -> bool:
  33.     valid_digits = DIGIT_VALUES[:base]
  34.     return all(char.upper() in valid_digits for char in number)
  35.  
  36.  
  37. def convert(number: str, orig_base: int, new_base: int) -> str:
  38.     if new_base == orig_base:  # if base is the same, just return the original number
  39.         return number
  40.  
  41.     if not is_valid_number(number, orig_base):
  42.         raise ValueError(f"{number} is not valid in {BASE_LABELS[orig_base]}.")
  43.  
  44.     result = 0
  45.     result_str = ""
  46.  
  47.     if orig_base != 10:  # convert the original number to base 10 before converting
  48.         # `enumerate` gives the index AND value in an iterable (in our case a string)
  49.         # `[::-1]` reverses an iterable using "slice notation"
  50.         for place, digit in enumerate(number[::-1]):
  51.             result += (orig_base**place) * char_to_value(digit)
  52.     else:
  53.         result = int(number)
  54.  
  55.     if new_base == 10:  # if the new base is already 10, the process is done
  56.         return str(result)
  57.  
  58.     while result > 0:
  59.         result, remainder = divmod(result, new_base)
  60.         result_str = value_to_char(remainder) + result_str
  61.  
  62.     return result_str or "0"
  63.  
  64.  
  65. if __name__ == "__main__":
  66.     print("=" * 32)
  67.     print(f"{'Base Converter':^32}")
  68.     print("=" * 32)
  69.  
  70.     orig_base = int(input("Input the original base: "))
  71.     new_base = int(input("Input the new base: "))
  72.     if any(base < 2 or base > 36 for base in (orig_base, new_base)):
  73.         print("Bases must be between 2 and 36!")
  74.         sys.exit(1)
  75.  
  76.     number = input("Input your number: ")
  77.  
  78.     try:
  79.         converted = convert(number, orig_base, new_base)
  80.         print(
  81.             f"{number} ({BASE_LABELS.get(orig_base, f'Base {orig_base}')})"
  82.             " = "
  83.             f"{converted} ({BASE_LABELS.get(new_base, f'Base {new_base}')})"
  84.         )
  85.     except ValueError as ve:
  86.         print(ve)
  87.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement