6

I'm trying to make a program to convert a number in any base to another base of the user's choice. The code I have so far goes like this:

innitvar = float(raw_input("Please enter a number: "))
basevar = int(raw_input("Please enter the base that your number is in: "))
convertvar = int(raw_input("Please enter the base that you would like to convert to: "))

These are the data that I get from the user. The initial number, its initial base, and the base the user wants to convert to. As I understand it, I need to convert to base 10, and then to the desired base, specified by the user.

This is where I'm hitting a brick wall: I need to multiply the leftmost digit in the initial number by its initial base, and then add the next digit to the right, and then repeat until I hit the rightmost digit. I understand how to do this on paper, but I have no idea how to put it into Python code. I'm not sure how I would multiply the first number, and then add the next, nor do I understand how to let the program know when to stop performing this operation.

I'm not asking to have the program written for me, but I would like to be pointed in the right direction.

Thanks for your time!

Noctis Skytower
  • 21,433
  • 16
  • 79
  • 117
Just a Student
  • 233
  • 2
  • 5
  • 9
  • What symbols are you assuming to use for your numbers? Base ten uses `0123456789`, and base sixteen (hexadecimal) adds `ABCDEF` to that list of symbols. To be ready to convert from any base to any other base, you must have a list of symbols ready with their values up to your highest supported base minus one. – Noctis Skytower Oct 19 '10 at 23:56
  • The way I understand it, I need to create a dictionary (which I more or less understand) to assign values to A-Z, so I can convert from any base to any base up to base 36. – Just a Student Oct 20 '10 at 00:07
  • The proper spelling is 'initial', by the way. – kenm Oct 20 '10 at 03:19
  • Please do not edit the question or answers for Python 3. Converting over to a newer version is not part of the lesson. – Noctis Skytower May 09 '16 at 15:10

9 Answers9

10

This should be the first half of the answer to your problem. Can you figure out how to convert to a base?

# Create a symbol-to-value table.
SY2VA = {'0': 0,
         '1': 1,
         '2': 2,
         '3': 3,
         '4': 4,
         '5': 5,
         '6': 6,
         '7': 7,
         '8': 8,
         '9': 9,
         'A': 10,
         'B': 11,
         'C': 12,
         'D': 13,
         'E': 14,
         'F': 15,
         'G': 16,
         'H': 17,
         'I': 18,
         'J': 19,
         'K': 20,
         'L': 21,
         'M': 22,
         'N': 23,
         'O': 24,
         'P': 25,
         'Q': 26,
         'R': 27,
         'S': 28,
         'T': 29,
         'U': 30,
         'V': 31,
         'W': 32,
         'X': 33,
         'Y': 34,
         'Z': 35,
         'a': 36,
         'b': 37,
         'c': 38,
         'd': 39,
         'e': 40,
         'f': 41,
         'g': 42,
         'h': 43,
         'i': 44,
         'j': 45,
         'k': 46,
         'l': 47,
         'm': 48,
         'n': 49,
         'o': 50,
         'p': 51,
         'q': 52,
         'r': 53,
         's': 54,
         't': 55,
         'u': 56,
         'v': 57,
         'w': 58,
         'x': 59,
         'y': 60,
         'z': 61,
         '!': 62,
         '"': 63,
         '#': 64,
         '$': 65,
         '%': 66,
         '&': 67,
         "'": 68,
         '(': 69,
         ')': 70,
         '*': 71,
         '+': 72,
         ',': 73,
         '-': 74,
         '.': 75,
         '/': 76,
         ':': 77,
         ';': 78,
         '<': 79,
         '=': 80,
         '>': 81,
         '?': 82,
         '@': 83,
         '[': 84,
         '\\': 85,
         ']': 86,
         '^': 87,
         '_': 88,
         '`': 89,
         '{': 90,
         '|': 91,
         '}': 92,
         '~': 93}

# Take a string and base to convert to.
# Allocate space to store your number.
# For each character in your string:
#     Ensure character is in your table.
#     Find the value of your character.
#     Ensure value is within your base.
#     Self-multiply your number with the base.
#     Self-add your number with the digit's value.
# Return the number.

def str2int(string, base):
    integer = 0
    for character in string:
        assert character in SY2VA, 'Found unknown character!'
        value = SY2VA[character]
        assert value < base, 'Found digit outside base!'
        integer *= base
        integer += value
    return integer

Here is the second half of the solution. By using these two functions, converting bases is very easy to do.

# Create a value-to-symbol table.
VA2SY = dict(map(reversed, SY2VA.items()))

# Take a integer and base to convert to.
# Create an array to store the digits in.
# While the integer is not zero:
#     Divide the integer by the base to:
#         (1) Find the "last" digit in your number (value).
#         (2) Store remaining number not "chopped" (integer).
#     Save the digit in your storage array.
# Return your joined digits after putting them in the right order.

def int2str(integer, base):
    array = []
    while integer:
        integer, value = divmod(integer, base)
        array.append(VA2SY[value])
    return ''.join(reversed(array))

After putting it all together, you should end up with the program below. Please take time to figure it out!

innitvar = raw_input("Please enter a number: ")
basevar = int(raw_input("Please enter the base that your number is in: "))
convertvar = int(raw_input("Please enter the base that you would like to convert to: "))

# Create a symbol-to-value table.
SY2VA = {'0': 0,
         '1': 1,
         '2': 2,
         '3': 3,
         '4': 4,
         '5': 5,
         '6': 6,
         '7': 7,
         '8': 8,
         '9': 9,
         'A': 10,
         'B': 11,
         'C': 12,
         'D': 13,
         'E': 14,
         'F': 15,
         'G': 16,
         'H': 17,
         'I': 18,
         'J': 19,
         'K': 20,
         'L': 21,
         'M': 22,
         'N': 23,
         'O': 24,
         'P': 25,
         'Q': 26,
         'R': 27,
         'S': 28,
         'T': 29,
         'U': 30,
         'V': 31,
         'W': 32,
         'X': 33,
         'Y': 34,
         'Z': 35,
         'a': 36,
         'b': 37,
         'c': 38,
         'd': 39,
         'e': 40,
         'f': 41,
         'g': 42,
         'h': 43,
         'i': 44,
         'j': 45,
         'k': 46,
         'l': 47,
         'm': 48,
         'n': 49,
         'o': 50,
         'p': 51,
         'q': 52,
         'r': 53,
         's': 54,
         't': 55,
         'u': 56,
         'v': 57,
         'w': 58,
         'x': 59,
         'y': 60,
         'z': 61,
         '!': 62,
         '"': 63,
         '#': 64,
         '$': 65,
         '%': 66,
         '&': 67,
         "'": 68,
         '(': 69,
         ')': 70,
         '*': 71,
         '+': 72,
         ',': 73,
         '-': 74,
         '.': 75,
         '/': 76,
         ':': 77,
         ';': 78,
         '<': 79,
         '=': 80,
         '>': 81,
         '?': 82,
         '@': 83,
         '[': 84,
         '\\': 85,
         ']': 86,
         '^': 87,
         '_': 88,
         '`': 89,
         '{': 90,
         '|': 91,
         '}': 92,
         '~': 93}

# Take a string and base to convert to.
# Allocate space to store your number.
# For each character in your string:
#     Ensure character is in your table.
#     Find the value of your character.
#     Ensure value is within your base.
#     Self-multiply your number with the base.
#     Self-add your number with the digit's value.
# Return the number.

integer = 0
for character in innitvar:
    assert character in SY2VA, 'Found unknown character!'
    value = SY2VA[character]
    assert value < basevar, 'Found digit outside base!'
    integer *= basevar
    integer += value

# Create a value-to-symbol table.
VA2SY = dict(map(reversed, SY2VA.items()))

# Take a integer and base to convert to.
# Create an array to store the digits in.
# While the integer is not zero:
#     Divide the integer by the base to:
#         (1) Find the "last" digit in your number (value).
#         (2) Store remaining number not "chopped" (integer).
#     Save the digit in your storage array.
# Return your joined digits after putting them in the right order.

array = []
while integer:
    integer, value = divmod(integer, convertvar)
    array.append(VA2SY[value])
answer = ''.join(reversed(array))

# Display the results of the calculations.
print answer
Noctis Skytower
  • 21,433
  • 16
  • 79
  • 117
  • I have never used tables or the def and return functions before. And I'm afraid that converting to a base is my problem, as I still do not know how to access individual digits in a number in order to multiply and add. – Just a Student Oct 20 '10 at 00:37
  • `def` and `return` are two different keywords in Python, not functions. `def` allows you to create a function or method (a body of code that you can reuse by making "calls" to it), and `return` allows that body of code to return one or more values back to the "caller." As for accessing individual digits in a number, it helps to understand that there are no "individual digits" in a number. The base of a number does not matter so much as the value of the number. When you are converting a number into a representable base (a printable string for instance), you have to chop the number up by a base. – Noctis Skytower Oct 20 '10 at 00:44
  • What do you mean by "chop the number up by a base."? If I can't take the "1" out of "1234" and multiply it, then add the "2", how am I supposed to convert to base 10? – Just a Student Oct 20 '10 at 00:53
  • Again, you are thinking in "individual digits." Please do not think about the digits in your number. The `str2int` function above return a number of the `int` data type. This number has a value, but it does not have "digits" that you can access. For example, `a = 16` assigns the decimal value of `16` to `a`. However, the decimal value of `16` has a representation (not value) of `10` in hexadecimal. Thinking about the value of the number regardless of the base or representation would be very helpful to you. Knowing the decimal "representation" is fine, but think in terms of the "value" instead. – Noctis Skytower Oct 20 '10 at 01:03
  • I'm just becoming more and more confused. I have been trying to figure this out for hours now, but I cannot understand how to convert a base X number to base 10 using python code. – Just a Student Oct 20 '10 at 01:12
  • What does the function `str2int` up above do? It converts a base X number having a string representation into a number having a value. That is what you want. The number that is returned from the function does not have a base; it has a value. Take that value and use `divmod` to create the values for the digits of the base that you are converting the value of the number into. A string representation of a number is just that: a representation. The number returned by the `str2int` function has a value -- and that is all. It is a number with a value; it has no base. You must convert it into a base. – Noctis Skytower Oct 20 '10 at 01:23
  • I'm sorry, I'm just very frustrated with this assignment. Would you be willing to give me an example of how this works so I can better understand it? – Just a Student Oct 20 '10 at 01:45
  • Okay, let's try "completing" the assignment and then try to figure out how it works after it is done. You have my apologies, but I must not be explaining this very well for your understanding. The solution to the problem is simple to me, so solving the problem and then reviewing the answer may be a better way to help you. Come back after a little while and look for the second part of the solution. – Noctis Skytower Oct 20 '10 at 01:54
  • The second half of the code is now available. Both parts are required, especially considering that the global variable `VA2SY` relies on the existence of `SY2VA` to be created. `VA2SY` could be defined as a list, tuple, or string and be more efficient; but to prevent confusion, it is defined as a dictionary with its key/value pairs reversed. If you have questions, please ask so that you can learn! – Noctis Skytower Oct 20 '10 at 02:39
  • Are your # notes explaining what is happening, or is it listing what still needs to be done? I'm asking because I did not see any input statements to get anything from the user. Sorry if this is a stupid question, my brain is more or less fried from stressing over this problem all night. – Just a Student Oct 20 '10 at 02:51
  • The notes are explaining what the code following it does. If you are allowed to use functions, then you should be able to use the code above as seen. You just need to make calls to `str2int` and `int2str`. However, if you need to write your program without functions, then you need to change the code so that "arguments" to the functions are named after the variables created at the top of your program. Otherwise, rename the variables created in the first three lines of your program. Then you should be able to remove the four spaces at before the lines in the functions. Finally, print the answer. – Noctis Skytower Oct 20 '10 at 03:54
  • Could you explain what you mean by "You just need to make calls to str2int and int2str." and "Then you should be able to remove the four spaces at before the lines in the functions."? A lot of this code is new to me, so I'm still figuring out what it all does. I am slowly learning though. – Just a Student Oct 20 '10 at 04:30
  • I'm also wondering if "integer" and "base" are the same as "innitvar" and basevar" in my first 3 lines. And what value represents. – Just a Student Oct 20 '10 at 04:48
  • Err, to clarify, by "value", I mean the variable that you named "value" in your program. – Just a Student Oct 20 '10 at 05:09
  • `value` in my code is the value of a digit from a number. It is not to be confused with the value of a number as a whole. To assemble a representation into the value of a number, you have to deal with the values of the individual digits. In `str2int`, it adds those values to the value of your the number `integer` after `integer` has been multiplied by the base. The `int2str` method, on the other hand, disassembles the value of a number into the individual values (or representation of values) into a number that can be read: a printable string. By the way, do not convert `innitvar` into a float. – Noctis Skytower Oct 20 '10 at 12:44
  • Would I be right to change your "integer" to innitvar and "base" to basevar? And would I leave value as it is? I'm still not sure what you mean by "call str2int and int2str", but I'll keep trying to figure it out in the two hours I have left to complete the assignment. – Just a Student Oct 20 '10 at 14:33
  • Also, I've tried changing integer to innitvar and base to basevar, and have tried printing innitvar and basevar, but they do not change. – Just a Student Oct 20 '10 at 14:37
  • They do not change in the output, rather. – Just a Student Oct 20 '10 at 14:52
  • A working program should be available now. Please make sure you figure out how it works and why it works as soon as possible (by this weekend). You are learning to program, and you are learning to think (like a programmer), but you will not learn if you do not take the time to understand what you are given. If you take this program and do not understand it, I have been a disservice to your teacher. If you figure out what the program is doing and why it was written the way it was, then you may learn something that you can use in programs you write in the future. I hope that helps you do better! – Noctis Skytower Oct 20 '10 at 15:53
  • Thank you for all of your help. I'll study over the program until I understand it completely. – Just a Student Oct 20 '10 at 16:59
  • In light of that fact that this is for an older version of Python as specified in the tags, the answer has been rolled back to a previous version that is not for Python 3. – Noctis Skytower May 09 '16 at 15:09
5

I need to multiply the leftmost digit in the initial number by its innitial base, and then add the next digit to the right, and then repeat until I hit the rightmost digit.

So you need to get digits. In a list.

Hint 1: Use divmod() function to break a number into digits. Divide by 10 to get decimal digits.

Hint 2: While n > 0: you can use divmod() to get a quotient and a remainder. If you save the remainder in the list, and use the quotient as the new value of n your number gets smaller until what's left is zero and you're done.

Hint 3: Your digits arrive in right-to-left order. Use reverse to switch the order of the list of this bothers you. Or create the list by using insert(0,digit).

Now that you have the digits. In a list. You can iterate through the list.

Try the for statement on for size.

You might need to use a "multiple and add" loop. total = total * new_base + next_digit is the way the body of the loop often looks.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • Your answer is good, and I'm upvoting it. However, I discourage the `insert(0, digit)` approach unless you're dealing with a linked list---with an array (which Python uses, IIRC), each `insert(0, digit)` is an O(n) operation. (The `reverse`-at-the-end approach is the best one, of course.) – C. K. Young Oct 20 '10 at 00:02
  • What you described is the method to use after getting your innitial base to base 10, correct? I'm understanding this part, but I'm not sure how to access individual digits in a number to multiply and add in order to move from innitial base to base 10. – Just a Student Oct 20 '10 at 00:10
  • @Chris Jester-Young. I'll assume you're talking about numbers with kabillions of digits. For ordinary 20-30 digit numbers, your optimization may not amount to much. – S.Lott Oct 20 '10 at 00:12
  • "You might need to use a "multiple and add" loop. total = total * new_base + next_digit is the way the body of the loop often looks." This is where I'm lost. I don't know how to multiply the first digit, then add the next, then repeat to the end. – Just a Student Oct 20 '10 at 00:18
  • @Just a Student: You have the digits in a list. They're separate numbers. Print the list. Look at it. Use `for i in someList:` to iterate through the digits/numbers. Try some code. Print stuff. Write `for` loops. Try things. Experiment. Explore. – S.Lott Oct 20 '10 at 01:29
4

Just a Student, slow down with the idea of what you need. You may not need what you think you need.

Start at the beginning: the user inputs a number. The user inputs a base. These are both Strings. Say the base is 12, and the number is 1AB3. So you have a '1' in the 12^3 place, an 'A' in the 12^2 place, a 'B' in 12^1, and a '3' in the 12^0 (ones) place. If you want this number in base 10, you're going to need to add some numbers together.

Specifically, you need to add 1*12^3 + 10*12^2 + 11*12^1 + 3*12^0. Notice something here: you have 3,2,1,0. Which corresponds nicely to the LENGTH of the input string 1AB3. So probably a for loop would be helpful here. The user doesn't input an integer, they input a string. So you need the characters from the string, not the digits from the number.

How do you know what the symbols 'A' and 'C' represent in decimal notation? Look at the answer from Noctis Skytower!

So your first task is to figure out how to ITERATE THROUGH A STRING. Your second task is to figure out how to use the individual character values from your string to access the dictionary in Noctis Skytower's answer, and your third task is to figure out how to write a loop that takes advantage of that information.

philosodad
  • 1,808
  • 14
  • 24
  • 1
    +1: Probably the most comprehensive answer to help this person understand, instead of just crapping out some response. – Andrew Sledge Oct 20 '10 at 16:17
  • Thanks for explaining the math behind the operations. Teachers do not teach what they assume the students already know. I focused on the language, but your teaching why numbers work the way they do should be much more helpful in the long run. :) – Noctis Skytower Oct 20 '10 at 16:53
2

You'll just need a simple program to read in values, then call this function to switch between bases. Provided the bases in question can be written using the Latin alphabet, i.e., base <= 36, then this function will return the number in the new base as a string.

It does use the built-in int function to arrive at base 10 for the conversion process, so if you're not supposed to use any built-in functions you'll have to handle that part yourself.

def changebase(n, base=10, to=10):
    '''
    params:
      n     - number to convert
      base  - current base of number 'n'
      to    - desired base, must be <= 36
    '''
    # check that new base is <= 36
    if to > 36 or base > 36:
        raise ValueError('max base is 36')

    # convert to base 10
    n = int(str(n), base)
    positive = n >= 0

    # return if base 10 is desired
    if to == 10:
        return str(n)

    # convert to new base
    n = abs(n)
    num = []
    handle_digit = lambda n: str(n) if n < 10 else chr(n + 55)
    while n > 0:
        num.insert(0, handle_digit(n % to))
        n = n // to

    # return string value of n in new base
    return ''.join(num) if positive else '-' + ''.join(num)
0

You need to write two functions. In Scheme (since I know Scheme much better than Python :-P), those two functions are called string->number and number->string, though of course you can name them whatever you like.

Each of those functions needs to take a base parameter to do the conversion in. You can make it default to 10, if you like.

Once you implement each of those successfully, the rest is a piece of cake.

Test cases for you:

assert str2num('1234', 10) == 1234
assert str2num('1234', 16) == 0x1234
assert num2str(1234, 10) == '1234'
assert num2str(1234, 16) == '4d2'
assert num2str(0x1234, 16) == '1234'
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • I'm sorry, but I'm -very- unskilled in Python. Could you explain what you mean by "In Scheme, those two functions are called string->number and number->string", as well as the code you typed? – Just a Student Oct 19 '10 at 23:52
  • So, you need to write two functions: in the test cases, I've named them `str2num` and `num2str`. The first one converts the given string to a number, using the given base. The second one converts the given number to its string representation in the given base. – C. K. Young Oct 19 '10 at 23:54
  • To get you started, you have to know to distinguish strings (the bits enclosed in quotes, in my test cases) and numeric values (the numbers not enclosed in quotes). Your `str2num` and `num2str` functions have to convert one form to the other. – C. K. Young Oct 19 '10 at 23:55
  • In Python, you can use `str('1234')` and `str(1234)` (for example) to tell you which is which. – C. K. Young Oct 19 '10 at 23:56
  • I suppose what I'm trying to ask is "What is assert? How is it used?". I'm really not getting the code. I don't see any calculations or anything like that, which comes back to my biggest problem, how to take the left digit and multiply, then add the right, and continue to the end of the number. – Just a Student Oct 19 '10 at 23:59
  • `assert` is pseudocode here. It just means, "this expression needs to be true". In other words, `str2num('1234', 16)` needs to have the same value as `0x1234`. As for the calculations themselves, that's something you have to figure out for yourself---this is homework after all. – C. K. Young Oct 20 '10 at 00:01
  • I just feel more confused now. The root of my problem is that I have no clue how to use individual digits in a number. – Just a Student Oct 20 '10 at 00:13
0

int() can convert strings from any base between 2 and 36. If you need a wider range than that then create a string containing the digits and use the index() method to get the value.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Surely, for a homework problem, you aren't allowed to use shortcuts like `int()`? ;-) – C. K. Young Oct 19 '10 at 23:57
  • @Chris: Learning how to use the built-in facilities is an important part of learning the language. – Ignacio Vazquez-Abrams Oct 19 '10 at 23:58
  • 1
    Yes, if the aim of the course is learning the language. But if the aim is actually to understand the operation of base conversion, with the language as purely a vehicle for practising that understanding, then the course requirements will reflect that. – C. K. Young Oct 19 '10 at 23:59
  • My professor discourages most shortcuts or unnecessary modules. He wants us to manually code in any calculations. – Just a Student Oct 20 '10 at 00:02
  • @Just a Student: `int()` is built-in to Python, no modules needed. – C. K. Young Oct 20 '10 at 00:04
  • I thought the int() function converted a none integer into an integer. I'm not sure how this helps with changing one base to another. – Just a Student Oct 20 '10 at 00:24
  • `int() can convert strings from any base between 2 and 36`? When I do: int('22', 8). I get 18. But 22 should be assumed to be base 10 right? How can I convert a string 22 to anybase? (like 9, 11 etc) – zengr Jul 22 '13 at 21:52
  • ... `>>> int('22', 9)` `20` `>>> int('22', 11)` `24` – Ignacio Vazquez-Abrams Jul 22 '13 at 22:03
0

I came here looking for shortcuts but looks like none exist. So here are the long methods I have found. This answer is based on an answer at Quora and also related to other answers here.

The easiest way(probably) is to convert any number from a base b1 to b2 is to convert b1→Decimal→b2.

A number in the base b1 can be treated like a polynomial in the base b1,

ie, a 4-digit number abcd = d*(b1^0)+c*(b1^1)+b*(b1^2)+a*(b1^3)

Eg., 123(Decimal) = 3*(10^0)+2*(10^1)+1*(10^2)

So, to convert from any base to Decimal, find the sum of all [digit*(base^power)] (where power is 0 to [NumOfDigits-1]) in the reverse order of the digits. For this, treat the number as a string and iterate through it using a for loop.

So, the input should be a string and the op an int.

The next step is to convert a Decimal number D to base b2.

Divide D/b2, the remainder is the rightmost digit. Divide the quotient by b2, the remainder this time is the next rightmost digit. Repeat this cycle until the quotient is 0.

Eg.,

8(Dec) to Binary:

8/2=4; 8%2=0

4/2=2; 4%2=0

2/2=1; 2%2=0

1/2=0; 1%2=1

8(Dec)=1000(Bin)

This is done by treating the output number as a string, and reversing the string after concatenating all the digits to it. (See above: '0' + '0' + '0' + '1' ='0001' , reverse it '1000'

For these two processes, the following python program would do:

    N=input("Num:")
    B1=int(input("FromBase:"))
    B2=int(input("ToBase:"))
    print("Base[",B1,"]:",N)

    #From Base B1 to Decimal
    DN=0
    for i in range(len(N)):
        DN+= int(N[::-1][i]) * (B1 ** i)
    print("Decimal:",DN)

    #From Decimal to Base B2
    if int(N) == 0:
        BN = 0
    else:
        BN = ""
        while DN > 0:
            BN += str(DN % B2)
            DN = int(DN / B2)
    print("Base[",B2,"]:",int(BN[::-1]))

But you’ll notice that this program is not practical while using bases more than 10. For this purpose, you need to use more digits to represent values more than 0-9. For that you will have to use long if-else ladders to select the digits according the face value or vise versa.

N=input("Num:")
B1=int(input("FromBase:"))
B2=int(input("ToBase:"))
print("Base[",B1,"]:",N)

#From Base B1 to Decimal
DN=0
for i in range(len(N)):
    if N[::-1][i] == '0':
        DN += 0 * (B1 ** i)
    elif N[::-1][i] == '1':
        DN += 1 * (B1 ** i)
    elif N[::-1][i] == '2':
        DN += 2 * (B1 ** i)
    '''    :
           :       '''
    elif N[::-1][i] == 'A':
        DN += 10 * (B1 ** i)
    '''    :
           :  (fill it) ....
           :       '''
print("Decimal:",DN)

#From Decimal to Base B2
if int(N) == 0:
    BN = 0
else:
    BN = ""
    while DN > 0:
        R = DN % B2
        if R==0:
            BN += '0'
        elif R==1:
            BN += '1'
        elif R==2:
            BN += '2'
        '''     :
                :
                :       '''
        elif R==10:
            BN += 'A'
        '''     :
                :
                :       '''
        DN = int(DN / B2)
print("Base[",B2,"]:",int(BN[::-1]))

Almost everyone avoids this long if-else ladder by using a dictionary with the face values as keys and the symbols/digits as their respective values. Now the program becomes:

Dig={0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F', 16: 'G', 17: 'H', 18: 'I', 19: 'J'}

N=input("Num:")
B1=int(input("FromBase:"))
B2=int(input("ToBase:"))
print("Base[",B1,"]:",N)

#From Base B1 to Decimal
DN=0
for i in range(len(N)):
    for fv in Dig:
        if Dig[fv]== N[::-1][i]:    # FaceValue of the Digit
            DN+= fv * (B1 ** i)
print("Decimal:",DN)

#From Decimal to Base B2
if N == '0':
    BN = 0
else:
    BN = ""
    while DN > 0:
        BN += Dig[DN % B2]          # Digit for the Value
        DN = int(DN / B2)
print("Base[",B2,"]:",BN[::-1])

There’s your homework. Select any on of those three methods.

To use even more bases, you can just expand the dictionary and create a long one like @Noctis Skytower.

Every single website I checked had long dictionaries like that, but I tend to use shortcuts for almost everything. I used simple range() function, if-else statements, and simple for loops to shorten the process(but I think it looks a bit confusing, despite being simple). The advantage of this is that it’s very easy to add more bases by just adding a key, range(a,b), for the range of face values of digits, and a value, range(x,y), for the range of Unicode values of the characters for the respective values.

Val = {range(10):range(48, 58), range(10,36): range(65, 91)}

N=input("Num:")
B1=int(input("FromBase:"))
B2=int(input("ToBase:"))
print("Base[",B1,"]:",N)

#From Base B1 to Decimal
DN = 0
for i in range(len(N)):
    for j in Val:
        if ord(N[i]) in Val[j]:
            FV=j[ord(N[i])-Val[j][0]]       # FaceValue of the Digit
    if FV>= B1:                             # Digits aren't >=Base, right?
        print("Base Error..")
        exit()
    else:
        DN += FV * (B1 ** (len(N) - 1 - i))
print("Decimal:",DN)

#From Decimal to Base B2
if int(DN) == 0:
    BN = '0'
else:
    BN = ""
    while DN > 0:
        R = DN % B2
        for i in Val:
            if R in i:
                BN+=chr(Val[i][R-i[0]])     #Finding the Digit for the Value
        DN = int(DN / B2)
print("Base[", B2, "]:", BN[::-1])

This can also be done using functions:

Val = {range(10):range(48, 58), range(10,36): range(65, 91)}

def B2D(N,B1):
    '''From Base B1 to Decimal'''
    DN = 0
    for i in range(len(N)):
        for j in Val:
            if ord(N[i]) in Val[j]:
                FV=j[ord(N[i])-Val[j][0]]       # FaceValue of the Digit
        if FV>= B1:                             # Digits aren't >=Base, right?
            print("Base Error..")
            exit()
        else:
            DN += FV * (B1 ** (len(N) - 1 - i))
    return DN

def D2B(DN,B2):
    '''From Decimal to Base B2'''
    if int(DN) == 0:
        BN = '0'
    else:
        BN = ""
        while DN > 0:
            R = DN % B2
            for i in Val:
                if R in i:
                    BN+=chr(Val[i][R-i[0]])     #Finding the Digit for the Value
            DN = int(DN / B2)
    return BN[::-1]

def B2B(N,B1,B2):
    return D2B(B2D(N,B1),B2)

N=input("Num:")
B1=int(input("FromBase:"))
B2=int(input("ToBase:"))
print("Base[",B1,"]:",N)
print("Decimal:",B2D(N,B1))
print("Base[",B2,"]:",B2B(N,B1,B2))

Now, if you can expand the dictionary, you can probably convert from any base to any base.

These are some shortcuts I found on other StackOverflow Q-A and other websites:

To convert nums from any base between 2 & 36 to Decimal: int(‘NumberString’,Base)

>>> int('1000',2)
8
>>> int('100',12)
144
>>> int('AA',17)
180
>>> int('Z',36)
35
>>> int('Z',37)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: int() base must be >= 2 and <= 36, or 0

To convert Decimal into Binary, Octal, and Hex:

>>> bin(8)
'0b1000'
>>> oct(8)
'0o10'
>>> hex(8)
'0x8'

Hope this TL;DR helped someone. If somebody can point out any mistakes, edit this, or provide shorter methods, I'll be grateful.

  • I'm planning to modify this to be able to work with fractions(floats) and negative numbers and more. Pls let me know if anyone can help. – Shaheem TP Sep 11 '19 at 10:04
0

there is a function that you need:

def convert_base(num, from_base=10, to_base=10):
    # first convert to decimal number
    if isinstance(num, str):
        n = int(num, from_base)
    else:
        n = int(num)
    # now convert decimal to 'to_base' base
    alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    if n < to_base:
        return alphabet[n]
    else:
        return convert_base(n // to_base, to_base) + alphabet[n % to_base]
MIkhail
  • 49
  • 8
-2

Its easy. First, I made a number.py

class number:
    def __init__(self, value: str, base):
        alphabet = [str(i) for i in range(10)] + [chr(i).upper() for i in range(97, 123)]
        self.val = [c for c in value]
        self.alph = alphabet[:base]
        self.last = self.alph[-1]
        self.first = self.alph[0]
        self.len_alph = len(alphabet)

    def last_that_is_not(self,number, target):
        for idx, c in enumerate(number[::-1]):
            if c != target: return len(number)-1 - idx
        return

    def next(self):
        # We look for the last letter that isn't equal to self.last
        change_loc = self.last_that_is_not(self.val, self.last)
        if change_loc is not None:
            elem = self.val[change_loc]
            new_letter = self.alph[self.alph.index(elem)+1]
            self.val[change_loc] = new_letter
        len_val = len(self.val)
        # In case last that is not isnt the last letter
        change_loc = -1 if change_loc is None else change_loc
        increment = change_loc == -1
        for idx in range(change_loc+1, len_val):
            self.val[idx] = self.alph[0]
        if increment:
            self.val = [self.alph[1]] + [self.alph[0] for i in range(len_val)]

    def prev(self):
        # we look for the last letter that isn't equal to self.first
        change_loc = self.last_that_is_not(self.val, self.first)
        if change_loc is not None:
            elem = self.val[change_loc]
            new_letter = self.alph[self.alph.index(elem)-1]
            self.val[change_loc] = new_letter
        len_val = len(self.val)
        # In case last that is not is first letter
        self.val = [alphabet[-1] for i in range(len_val - 1)]


    def __repr__(self):
        return ''.join(self.val)
    __str__ = __repr__

then main.py

#!/usr/bin/pypy3
from time import time
from math import log, ceil
from number import number as num_baseX

# converts a number from base base to base 10
def convert2int(number, base = 10):
    number = number.upper()
    result = 0
    l = int(base**(len(number) - 1))
    for n in number:
        if '0' <= n <= '9':
            result += l*(ord(n) - ord('0'))
        else:
            result += l*(ord(n) - 55)
            # ord('A') - 10 = 55
        l = round(l/base)
    return result

# convertit un nombre de base 10 en
# un nombre de base base, base <= 36
def base10toX(number: int, base=10):
    start = ''.join(['0' for _ in range(ceil(log(number, base)))])
    start = '0'
    result = num_baseX(start, base)
    def _wrapper(number: int, base = 10):
        nonlocal result
        log_num = int(log(number, base))
        for i in range(base**log_num):
            result.next()
        number = number - base**log_num
        if number > 0:
            _wrapper(number, base)
    _wrapper(number, base)
    return result

def baseXtoY(**kwargs):
    """
    Usage:
    baseXtoY(num, X, Y)
    num = number
    X = base of num
    Y = base to convert to
    """
    integer_num = convert2int(kwargs['num'], kwargs['X'])
    return base10toX(integer_num, kwargs['Y'])

NOTE: I, L. Pham-Trong wrote this code. It is protected by the 4-close BSD licence :

Copyright (c) 2021, Luca PHAM-TRONG
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. All advertising materials mentioning features or use of this software must
   display the following acknowledgement:
     This product includes software developed by L. Pham-Trong, and this guy rocks.

4. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Luca Sans S
  • 118
  • 8