Python - 作业 - 将任意基数转换为任意基数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3973685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 13:38:21  来源:igfitidea点击:

Python - Homework - Converting Any Base to Any Base

pythonpython-2.7

提问by Just a Student

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.

这些是我从用户那里得到的数据。初始数字、其初始基数以及用户想要转换为的基数。据我了解,我需要转换为基数 10,然后转换为用户指定的所需基数。

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.

这就是我碰到砖墙的地方:我需要将初始数字中最左边的数字乘以其初始基数,然后将下一个数字添加到右边,然后重复直到我击中最右边的数字。我了解如何在纸上执行此操作,但我不知道如何将其放入 Python 代码中。我不确定如何将第一个数字相乘,然后添加下一个,我也不知道如何让程序知道何时停止执行此操作。

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!

谢谢你的时间!

采纳答案by Noctis Skytower

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

回答by Chris Jester-Young

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

您需要编写两个函数。在 Scheme 中(因为我比 Python 更了解 Scheme :-P),这两个函数被称为string->numberand number->string,当然你可以随意命名它们。

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.

这些函数中的每一个都需要接受一个基本参数来进行转换。如果愿意,您可以将其默认为 10。

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'

回答by Ignacio Vazquez-Abrams

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.

int()可以从 2 到 36 之间的任何基数转换字符串。如果您需要比该范围更广的范围,则创建一个包含数字的字符串并使用该index()方法获取值。

回答by S.Lott

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.

提示 1:使用divmod()函数将数字分解为数字。除以 10 得到十进制数字。

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 nyour number gets smaller until what's left is zero and you're done.

提示 2:当n> 0 时:可以使用divmod()得到商和余数。如果您将余数保存在列表中,并使用商作为n的新值,您的数字会变小,直到剩下的为零,您就完成了。

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

提示 3:您的数字按从右到左的顺序到达。使用reverse切换这困扰你的列表的顺序。或者使用insert(0,digit).

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

现在你有了数字。在一个列表中。您可以遍历列表。

Try the forstatement on for size.

试试for关于尺寸的声明。

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

您可能需要使用“多重加加”循环。 total = total * new_base + next_digit是循环体通常看起来的方式。

回答by philosodad

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.

从头开始:用户输入一个数字。用户输入基数。这两个都是字符串。假设基数是 12,数字是 1AB3。因此,您在 12^3 的位置有一个“1”,在 12^2 的位置有一个“A”,在 12^1 的位置有一个“B”,在 12^0(个)的位置有一个“3”。如果你想要这个数字以 10 为基数,你需要将一些数字相加。

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 forloop 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.

具体需要加1*12^3 + 10*12^2 + 11*12^1 + 3*12^0。注意这里的一些东西:你有 3,2,1,0。这很好地对应于输入字符串 1AB3 的 LENGTH。所以for在这里循环可能会有所帮助。用户输入的不是整数,而是字符串。所以你需要字符串中的字符,而不是数字中的数字。

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

你怎么知道符号“A”和“C”用十进制表示法代表什么?看看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.

因此,您的首要任务是弄清楚如何通过字符串进行迭代。您的第二个任务是弄清楚如何使用字符串中的单个字符值来访问 Noctis Skytower 答案中的字典,而您的第三个任务是弄清楚如何编写一个利用该信息的循环。

回答by Shaheem TP

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 Quoraand also related to other answers here.

我来到这里寻找捷径,但看起来不存在。所以这里是我找到的长方法。此答案基于Quora的答案,也与此处的其他答案相关。

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

最简单的方法(可能)是将任何数字从基数 b1 转换为 b2 是转换 b1→Decimal→b2。

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

一个以 b1 为底的数可以被当作一个以 b1 为底的多项式,

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

即 4 位数字 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)

例如,123(十进制) = 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 stringand iterate through it using a forloop.

因此,要将任何基数转换为十进制数,请按数字的相反顺序找到所有数的总和[digit*(base^power)](其中幂为 0 到 [NumOfDigits-1])。为此,将数字视为 astring并使用for循环遍历它。

So, the input should be a stringand the op an int.

所以,输入应该是 astring和 op an int

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

下一步是将十进制数 D 转换为基数 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.

除以 D/b2,余数为最右边的数字。将商除以 b2,这次的余数是下一个最右边的数字。重复这个循环,直到商为 0。

Eg.,

例如。,

8(Dec) to Binary:

8(12 月)到二进制:

8/2=4; 8%2=0

8/2=4;8%2=0

4/2=2; 4%2=0

4/2=2;4%2=0

2/2=1; 2%2=0

2/2=1;2%2=0

1/2=0; 1%2=1

1/2=0;1%2=1

8(Dec)=1000(Bin)

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'

这是通过将输出数字视为字符串并在将所有数字连接到字符串后反转字符串来完成的。(见上文:'0' + '0' + '0' + '1' ='0001',反转它'1000'

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

对于这两个进程,以下 python 程序将执行以下操作:

    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-elseladders to select the digits according the face value or vise versa.

但是你会注意到这个程序在使用大于 10 的基数时并不实用。为此,你需要使用更多的数字来表示大于 0-9 的值。为此,您将不得不使用长if-else梯子根据面值选择数字,反之亦然。

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-elseladder by using a dictionary with the face values as keys and the symbols/digits as their respective values. Now the program becomes:

几乎每个人都if-else通过使用以面值作为键和符号/数字作为各自值的字典来避免这个长阶梯。现在程序变成:

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.

要使用更多基数,您可以扩展字典并创建一个像@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-elsestatements, and simple forloops 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.

我查过的每一个网站都有这样的长字典,但我倾向于对几乎所有事情都使用快捷方式。我使用简单的range()函数、if-else语句和简单的for循环来缩短过程(但我认为它看起来有点混乱,尽管很简单)。这样做的好处是很容易添加更多的基数,只需添加一个键,range(a,b), 表示数字的面值范围,以及一个值,range(x,y),表示各个值的字符的 Unicode 值范围。

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 anybase to anybase.

现在,如果您可以扩展字典,您可能可以从任何基数转换为任何基数。

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

这些是我在其他 StackOverflow QA 和其他网站上找到的一些快捷方式:

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

要将 nums 从 2 和 36 之间的任何基数转换为十进制: 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;DRhelped someone. If somebody can point out any mistakes, edit this, or provide shorter methods, I'll be grateful.

希望这TL;DR对某人有所帮助。如果有人能指出任何错误、编辑它或提供更短的方法,我将不胜感激。