|
| 1 | +bases = { |
| 2 | + "binary": 2, |
| 3 | + "octal": 8, |
| 4 | + "decimal": 10, |
| 5 | + "hex": 16, |
| 6 | + "hexadecimal": 16 |
| 7 | +} |
| 8 | + |
| 9 | +default = 10 |
| 10 | + |
| 11 | + |
| 12 | +def verify_base(x): |
| 13 | + """ |
| 14 | + Verify if already is an integer |
| 15 | + If is not verify if is in the bases |
| 16 | + If is not return the default base |
| 17 | + """ |
| 18 | + try: |
| 19 | + return int(x) |
| 20 | + except: |
| 21 | + if x in bases: |
| 22 | + return bases[x] |
| 23 | + else: |
| 24 | + return default |
| 25 | + |
| 26 | + |
| 27 | +def decimal_value(x): |
| 28 | + """ |
| 29 | + ord(x) is a function that return the number in asc2 table |
| 30 | + we use ord to get the number of an caracter |
| 31 | + """ |
| 32 | + # TODO verify if in the base exist the character like: |
| 33 | + # 'z' doesnt exisist in decimal values |
| 34 | + if(x >= '0' and x <= '9'): |
| 35 | + return int(x) |
| 36 | + elif(x >= 'a' and x <= 'z'): |
| 37 | + return int(ord(x) - ord('a') + 10) |
| 38 | + elif(x >= 'A' and x <= 'Z'): |
| 39 | + return int(ord(x) - ord('A') + 10) |
| 40 | + else: |
| 41 | + # Error |
| 42 | + raise Exception('Number not valid for: ', x) |
| 43 | + |
| 44 | + |
| 45 | +def to_special_caracter(x): |
| 46 | + if(x >= 0 and x <= 9): |
| 47 | + return str(x) |
| 48 | + elif(x > 9): |
| 49 | + return chr(ord('a') + x - 10) |
| 50 | + else: |
| 51 | + raise Exception('Not valid negative number in converter: ', x) |
| 52 | + |
| 53 | + |
| 54 | +def convert(n, from_base, to_base): |
| 55 | + """ |
| 56 | + This algorithm convert numbers between any base to any base like: |
| 57 | +
|
| 58 | + convert("10",2,10) |
| 59 | + ~> "2" |
| 60 | +
|
| 61 | + This function recive 3 parameters |
| 62 | + n -> the number |
| 63 | + from_base -> base of n | you can pass as number like base 2 or as string like "binary" |
| 64 | + to_base -> base of the result | you can pass as number like base 2 or as string like "binary" |
| 65 | +
|
| 66 | + Why the n and the return is an string? |
| 67 | + Because bases greater the 10 use leathers to represents the numbers |
| 68 | + """ |
| 69 | + # TODO verify if number is negative |
| 70 | + |
| 71 | + n = str(n) |
| 72 | + from_base = verify_base(from_base) |
| 73 | + to_base = verify_base(to_base) |
| 74 | + |
| 75 | + # We convert to decimal because is the easy way to convert to all |
| 76 | + multi = 1 |
| 77 | + decimal_number = 0 |
| 78 | + if(from_base == 10): |
| 79 | + decimal_number = int(n) |
| 80 | + else: |
| 81 | + for i in range(len(n) - 1, -1, -1): |
| 82 | + decimal_number += (multi * decimal_value(n[i])) |
| 83 | + multi *= from_base |
| 84 | + |
| 85 | + if(to_base == 10): |
| 86 | + return str(decimal_number) |
| 87 | + |
| 88 | + result = "" |
| 89 | + |
| 90 | + while(decimal_number > 0): |
| 91 | + value = decimal_number % to_base |
| 92 | + result = to_special_caracter(value) + result |
| 93 | + decimal_number = int((decimal_number - value)/to_base) |
| 94 | + |
| 95 | + return result |
| 96 | + |
| 97 | + |
| 98 | +def test_convert(): |
| 99 | + print(convert("1111000111", 2, 8) == "1707") |
| 100 | + print(convert("1111000111", 2, 10) == "967") |
| 101 | + print(convert("1111000111", 2, 16) == "3c7") |
| 102 | + print(convert("1234567", 8, 2) == "1010011100101110111") |
| 103 | + print(convert("1234567", 8, 10) == "342391") |
| 104 | + print(convert("1234567", 8, 16) == "53977") |
| 105 | + print(convert("987123", 10, 2) == "11110000111111110011") |
| 106 | + print(convert("987123", 10, 8) == "3607763") |
| 107 | + print(convert("987123", 10, 16) == "f0ff3") |
| 108 | + print(convert("abcdef", 16, 2) == "101010111100110111101111") |
| 109 | + print(convert("abcdef", 16, 8) == "52746757") |
| 110 | + print(convert("abcdef", 16, 10) == "11259375") |
| 111 | + |
| 112 | + print(convert("179", 10, 16) == "b3") |
| 113 | + print(convert("b3", 16, 10) == "179") |
| 114 | + |
| 115 | +test_convert() |
0 commit comments