4

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

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 代码中。我不确定如何将第一个数字相乘,然后添加下一个数字,我也不明白如何让程序知道何时停止执行此操作。

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

谢谢你的时间!

4

8 回答 8

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
于 2010-10-20T00:29:50.073 回答
5

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

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

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

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

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

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

试试for关于尺寸的说法。

您可能需要使用“多重和添加”循环。 total = total * new_base + next_digit是循环体通常的外观。

于 2010-10-19T23:58:59.893 回答
4

只是一个学生,放慢你需要什么的想法。你可能不需要你认为你需要的东西。

从头开始:用户输入一个数字。用户输入一个碱基。这些都是字符串。假设底数是 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 的长度。所以可能一个for循环在这里会有所帮助。用户不输入整数,而是输入字符串。所以你需要字符串中的字符,而不是数字中的数字。

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

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

于 2010-10-20T16:11:12.493 回答
0

您需要编写两个函数。在 Scheme 中(因为我比 Python 更了解 Scheme :-P),这两个函数被称为string->numberand number->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'
于 2010-10-19T23:48:41.587 回答
0

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

于 2010-10-19T23:52:56.480 回答
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)
于 2021-03-04T18:46:22.447 回答
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)] (其中幂为 0 到 [NumOfDigits-1])。为此,将数字视为 astring并使用循环遍历它for

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

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

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

例如。,

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(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)来表示数字的面值范围,并添加一个值 ,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 QA 和其他网站上找到的一些快捷方式:

要将 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

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

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

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

于 2019-07-26T17:38:11.390 回答
-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.
于 2021-02-15T23:44:41.803 回答