Python - 作业 - 将任何进制转换为任何进制

6
我正在尝试编写一个程序,将任何进制的数字转换为用户选择的另一个进制。到目前为止,我已经编写了以下代码:
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: "))

这些是我从用户那里得到的数据。初始数字,它的初始进制以及用户想要转换到的进制。据我所知,我需要先转换为十进制,然后再转换为用户指定的目标进制。
这就是我遇到的瓶颈:我需要将初始数字中最左边的数字乘以它的初始进制,然后加上右边的下一个数字,重复直到达到最右边的数字。我知道如何在纸上做到这一点,但我不知道如何将它编写成Python代码。我不确定如何乘以第一个数字,然后添加下一个数字,也不明白如何让程序知道何时停止执行此操作。
我不是要求为我编写程序,但我希望能指引我正确的方向。
感谢您花费时间!

你打算使用哪些符号来表示数字?十进制使用 0123456789,十六进制则在此基础上添加了 ABCDEF。为了能够从任意进制转换到另一种进制,你必须准备好一个符号列表,并将它们的值列出来,直到你支持的最高进制减一。 - Noctis Skytower
据我理解,我需要创建一个字典(我或多或少地理解)来为A-Z分配值,以便我可以将任何基数转换为最高36进制的任何基数。 - Just a Student
顺便说一下,正确的拼写是“initial”。 - kwatford
请勿为Python3编辑问题或答案。转换到更新版本不是本课程的一部分。 - Noctis Skytower
9个回答

10

这应该是解决你问题的前半部分答案。你能想出如何将其转换为基数吗?

# 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

这是解决方案的后半部分。通过使用这两个函数,转换进制非常容易。

# 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))

将所有内容整合后,您应该得到以下程序。请花些时间理解它!
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

我以前从未使用过表格或 def 和 return 函数。而且我担心将其转换为基数是我的问题,因为我仍然不知道如何访问数字中的个别数字以进行乘法和加法。 - Just a Student
defreturn是Python中两个不同的关键字,而不是函数。def允许您创建一个函数或方法(一段可以通过“调用”重复使用的代码),而return允许该代码块将一个或多个值返回给“调用者”。至于访问数字中的单个数字,需要了解数字中没有“单个数字”。数字的基数并不重要,数字的值才是最重要的。当您将数字转换为可表示的基数(例如可打印字符串)时,必须按基数切割数字。 - Noctis Skytower
请不要考虑数字中的每个单独数字,你需要从整体上思考。上面的str2int函数返回一个int数据类型的数字。这个数字有一个值,但是它没有可以访问的“数字”。例如,a = 16将十进制值16赋给a。然而,十进制值16在十六进制中的表示(而不是值)为10。无论基数或表示法如何,考虑数字的值而不是其表示形式会对你非常有帮助。知道十进制的“表示”是好的,但是请从“值”的角度来思考。 - Noctis Skytower
代码的后半部分现在已经可用。两个部分都是必需的,特别是考虑到全局变量VA2SY依赖于存在SY2VA才能被创建。VA2SY可以定义为列表、元组或字符串,并且更有效率;但为了避免混淆,它被定义为一个字典,其键/值对被反转。如果您有问题,请提出,以便您学习! - Noctis Skytower
你的#注释是在解释正在发生什么,还是列出了仍需完成的任务?我问这个问题是因为我没有看到任何输入语句来从用户获取任何内容。如果这是一个愚蠢的问题,请原谅,因为我整晚都为这个问题感到紧张,我的大脑已经几乎崩溃了。 - Just a Student
显示剩余16条评论

5
我需要将初始数字的最左侧数字乘以其初始基数,然后加上右侧的下一个数字,然后重复此过程,直到达到最右侧数字。 因此,您需要获取数字。在列表中。
提示1:使用divmod()函数将数字拆分为数字。除以10可获得小数位数字。
提示2:当n> 0时:您可以使用divmod()来获取商和余数。如果将余数保存在列表中,并使用商作为新值,则您的数字会变小,直到剩下零为止,然后完成。
提示3:您的数字以从右到左的顺序到达。如果这让您感到困扰,请使用reverse将列表的顺序进行切换。或者使用insert(0,digit)创建列表。
现在您有了数字。在列表中。您可以遍历列表。
尝试使用for语句。
您可能需要使用“多倍增加”循环。total = total * new_base + next_digit通常是循环体的方式。

你的回答很好,我会点赞。但是,我不鼓励使用 insert(0, digit) 的方法,除非你在处理链表——对于数组(Python 使用的是数组,如果我没记错的话),每个 insert(0, digit) 都是一个 O(n) 操作。(当然,最好的方法是在最后使用 reverse。) - C. K. Young
你所描述的是在将初始进制转换为十进制后使用的方法,对吗?我理解了这一部分,但我不确定如何访问数字中的个别数字以进行乘法和加法运算,以便从初始进制转移到十进制。 - Just a Student
@Chris Jester-Young。我会认为你在谈论具有数十亿位数字的数字。对于普通的20-30位数字,您的优化可能不会带来太多影响。 - S.Lott
你可能需要使用“多重加法”循环。total = total * new_base + next_digit 是循环体通常的样子。这就是我迷失的地方。我不知道如何先乘以第一个数字,然后再加上下一个数字,然后重复到最后。 - Just a Student
@Just a Student:你有一个数字列表。它们是分开的数字。打印出这个列表。看一下它。使用for i in someList:来遍历这些数字。尝试一些代码。打印一些东西。编写for循环。尝试一些东西。实验。探索。 - S.Lott

4

作为学生,慢慢思考你需要什么。你可能并不需要你认为需要的。

从开始入手:用户输入一个数字和一个进制。这两个都是字符串。假设进制是12,数字是1AB3。所以在12^3位置有一个'1',在12^2位置有一个'A',在12^1位置有一个'B',在12^0(个位)位置有一个'3'。如果你想把这个数转换成十进制,你需要加一些数字。

具体来说,你需要加上 1*12^3 + 10*12^2 + 11*12^1 + 3*12^0。注意一下:你有3、2、1、0四个数字。这与输入字符串1AB3的长度相对应。因此,也许一个for循环会有所帮助。用户输入的不是整数,而是字符串。因此,你需要使用字符串中的字符,而不是数字。

如何知道'A'和'C'在十进制表示中代表什么?看一下Noctis Skytower的答案!

因此,你的第一个任务是弄清楚如何遍历字符串。第二个任务是弄清楚如何使用字符串中的单个字符值来访问Noctis Skytower答案中的字典,第三个任务是弄清楚如何编写循环来利用这些信息。


1
+1:这可能是最全面的答案,可以帮助这个人理解问题,而不是仅仅回答一些废话。 - Andrew Sledge
感谢您解释了操作背后的数学原理。老师们不会教授他们认为学生已经知道的内容。我一直专注于语言方面,但是您教授数字工作方式的原因将在长期内更有帮助。 :) - Noctis Skytower

2
你只需要一个简单的程序来读入值,然后调用这个函数来在不同进制之间进行转换。只要所涉及的进制可以使用拉丁字母来表示,即进制 <= 36,那么这个函数将会返回一个字符串形式的新进制下的数值。
它确实使用了内置的 int 函数来将值转换为十进制,因此如果你不能使用任何内置函数,那么你需要自己处理这部分内容。
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

你需要编写两个函数。在Scheme中(因为我比Python更熟悉Scheme :-P),这两个函数分别被称为string->numbernumber->string,当然你可以随意命名。

每个函数都需要一个基数参数来进行转换。如果你愿意,可以将其默认设置为10。

一旦你成功实现了这两个函数,剩下的就非常简单了。

以下是测试用例:

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'

对不起,我在 Python 方面非常不熟练。你能解释一下你所说的“在 Scheme 中,这两个函数分别被称为 string->number 和 number->string”,并且你输入的代码是什么吗? - Just a Student
所以,您需要编写两个函数:在测试用例中,我已经将它们命名为 str2numnum2str。第一个函数将给定的字符串转换为数字,使用给定的进制。第二个函数将给定的数字转换为其在给定进制下的字符串表示形式。 - C. K. Young
为了让你开始,你必须知道如何区分字符串(在我的测试用例中用引号括起来的位)和数字值(未用引号括起来的数字)。你的 str2numnum2str 函数必须将一种形式转换为另一种形式。 - C. K. Young
我想问的是,“assert是什么?它怎么使用?”我真的不理解这段代码。我没有看到任何计算或类似的内容,这也是我最大的问题,如何取左侧数字并乘以右侧数字,然后继续到数字结尾。 - Just a Student
我现在感到更加困惑了。我的问题根源在于我不知道如何使用数字中的个位数。 - Just a Student
显示剩余2条评论

0

int()可以将2到36进制之间的字符串转换成整数。如果需要更大的范围,请创建包含数字的字符串,使用index()方法获取值。


当然,对于一个作业问题,你不能使用像int()这样的快捷方式,是吧?;-) - C. K. Young
1
是的,如果课程的目的是学习语言,那么可以这样做。但是,如果课程的目的实际上是理解基本转换的操作,并将语言纯粹作为练习这种理解的工具,那么课程要求将反映出这一点。 - C. K. Young
我以为int()函数可以将非整数转换为整数。我不确定这对于将一种基础转换为另一种有何帮助。 - Just a Student
int()可以将任何2到36进制的字符串转换为整数。当我执行int('22', 8)时,结果是18。但是22应该被认为是10进制,对吗?我如何将字符串22转换为任何进制(例如9、11等)? - zengr
>>> int('22', 9) 20 >>> int('22', 11) 24 - Ignacio Vazquez-Abrams
显示剩余3条评论

0

我来到这里是想寻找快捷方式,但似乎并不存在。以下是我找到的长方法。

这个答案基于Quora上的一个答案,也与其他答案相关。

最简单的方法(可能)是将任何一个从b1进制数转换为b2进制数,就是将b1→十进制→b2。

一个在b1进制下的数字可以被看作是在b1进制下的多项式,

即,一个4位数abcd=d*(b1^0)+c*(b1^1)+b*(b1^2)+a*(b1^3)

例如,123(十进制) = 3*(10^0)+2*(10^1)+1*(10^2)

所以,要从任何进制转换为十进制,找出所有[digit*(base^power)](其中power为0至[NumOfDigits-1])的和,按照数字的相反顺序。为此,将数字视为字符串,使用for循环迭代。

因此,输入应该是一个 string,输出是一个 int

下一步是将十进制数 D 转换为基数 b2。

将 D/b2 进行除法运算,余数是最右边的数字。 将商再次除以 b2,这次的余数是下一个右边的数字。 重复这个过程,直到商为 0。

Eg.,

8(十进制)转二进制:

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(十进制)=1000(二进制)

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

对于这两个过程,以下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]))

但是你会注意到,当使用超过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]))

几乎每个人都会避免使用冗长的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])

这是你的作业。选择其中任何一种方法。

要使用更多的进制,你可以扩展字典并创建一个像 @Noctis Skytower 这样的长字典。

我查看的每个网站都有类似的长字典,但我倾向于几乎所有事情都使用快捷方式。我使用简单的 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])

这也可以使用函数来完成:

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))

现在,如果您可以扩展字典,那么您可能可以将任何进制转换为任何进制。

以下是我在其他StackOverflow Q-A和其他网站上发现的一些快捷方式:

将介于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

将十进制转换为二进制、八进制和十六进制:

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

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

我计划修改这个程序,使其能够处理分数(浮点数)、负数等更多情况。如果有人能帮忙,请告诉我。 - Shaheem TP

0
你需要的是一个函数:
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]

-2

很简单。 首先,我创建了一个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__

然后是 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'])

注意:此代码由L. Pham-Trong编写,受4-clause BSD许可保护:

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.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接