Python - 家庭作业 - 将任何基础转换为任何基础

时间:2010-10-19 23:39:04

标签: python python-2.7

我正在尝试制作一个程序,将任何基数中的数字转换为用户选择的另一个基数。到目前为止我的代码是这样的:

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

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

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

我不是要求为我编写程序,但我想指出正确的方向。

谢谢你的时间!

8 个答案:

答案 0 :(得分:7)

这应该是问题答案的前半部分。你能弄清楚如何转换成基地吗?

# 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

答案 1 :(得分:5)

  

我需要将初始数字中最左边的数字乘以其固有基数,然后将下一个数字添加到右边,然后重复直到我点到最右边的数字。

所以你需要得到数字。在列表中。

提示1:使用divmod()功能将数字分成数字。除以10得到十进制数字。

提示2:当 n &gt; 0:您可以使用divmod()来获得商和余数。如果您将剩余部分保存在列表中,并使用商作为 n 的新值,那么您的数字会变小,直到剩下的数字为零并且您已完成。

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

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

请尝试for语句的大小。

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

答案 2 :(得分:2)

只是学生,慢慢想到你需要的东西。你可能不需要你认为你需要的东西。

从头开始:用户输入一个数字。用户输入基数。这些都是字符串。假设基数为12,数字为1AB3。所以你在12 ^ 3的地方有一个'1',在12 ^ 2的地方有一个'A',在12 ^ 1的地方有一个'B',在12 ^ 0(个)的地方有一个'3'。如果你想要这个数字在10的基数,你需要在一起添加一些数字。

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

你怎么知道符号'A'和'C'用十进制表示法表示什么?看看Noctis Skytower的答案!

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

答案 3 :(得分:0)

您需要编写两个函数。在Scheme中(因为我知道Scheme比Python更好:-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'

答案 4 :(得分:0)

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

答案 5 :(得分:0)

我来这里是为了寻找捷径,但似乎不存在。所以这是我发现的长方法。 此答案基于Quora处的答案,并且还与此处的其他答案有关。

最简单的方法(可能是将任何数字从基数b1转换为b2)是将b1→Decimal→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)] (幂为0到[NumOfDigits-1])的总和。 为此,请将数字视为string,然后使用for循环对其进行遍历。

因此,输入应为string,输入应为int

下一步是将小数D转换为基数b2。

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

例如,

8(Dec)转换为二进制:

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)

这是通过将输出数字视为字符串,并在将所有数字连接到字符串之后反转字符串来完成的。 (请参见上文:'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),并为Unicode值范围添加值range(x,y),就可以轻松添加更多基数。各个值的字符。

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

现在,如果您可以扩展字典,则可以将 any 基转换为 any 基。 ?

这些是我在其他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帮助了某人。如果有人可以指出任何错误,进行编辑或提供更短的方法,我将不胜感激。

答案 6 :(得分:0)

您只需要一个简单的程序来读取值,然后调用此函数在基数之间切换。如果有问题的基数可以使用拉丁字母书写,即基数 <= 36,那么此函数将返回新基数中的数字作为字符串。

它确实使用内置 int 函数来达到转换过程的基数 10,因此如果您不应该使用任何内置函数,则必须自己处理该部分。

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)

答案 7 :(得分:-1)

很简单。 首先,我做了一个 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-close 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.