将十进制值转换为二进制、十六进制和八进制的单一函数无法转换为二进制

3
我尝试构建一个标准函数,将任何十进制值转换为它的八进制、十六进制和二进制等价物,但出于某些原因,它不能处理二进制。我尝试在条件语句中加入额外的预防措施来检查基数为2,但仍然无法正常工作。
这是函数(我知道这对十六进制值不起作用。我之后会处理它):
def convert(num, base):
    remainder = num % base
    conv = []

    if(remainder == 0):
        conv.append('0')
    elif(remainder != 0 and base == 2):
        conv.append('1')
    else:
        conv.append(str(remainder))

    result = ''.join(conv)
    output = result[::-1]

    return int(output)

在代码行 elif(remainder != 0 and base == 2): 中,我检查余数不为0且基数为2时,向临时列表 conv 添加1。然后将列表转换为字符串,反转并将其作为整数返回。
例如,如果输入是 17,则输出需为:
    1     1     1     1
    2     2     2    10
    3     3     3    11
    4     4     4   100
    5     5     5   101
    6     6     6   110
    7     7     7   111
    8    10     8  1000
    9    11     9  1001
   10    12     A  1010
   11    13     B  1011
   12    14     C  1100
   13    15     D  1101
   14    16     E  1110
   15    17     F  1111
   16    20    10 10000
   17    21    11 10001

这些函数负责输入和输出打印:
def print_formatted(number):
    # your code goes here

    for i in range(number):
        print(
            str(i + 1) + " " + 
            str(convert(i + 1, 8)) + " " + 
            str(convert(i + 1, 16)) + " " + 
            str((convert(i + 1, 2)))
            )


if __name__ == '__main__':
    n = int(input())
    print_formatted(n)

更新

与其整个方程式都处理,我决定使用内置函数并修剪前两个字符(即0b),以便它符合格式。我试图基于二进制输出的宽度将它们相互分离,但我无法找到一种方法来实现。目前为止,这就是我所拥有的。

def convert(num, base):
    # get the highest power
    val = ''
    hex_char_list = ['A', 'B', 'C', 'D', 'E', 'F']

    if(base == 2):
        bin_num = bin(num)
        bin_list = list(bin_num)
        bin_list_2 = bin_list[2:]
        val = ''.join(bin_list_2)

    if(base == 8):
        oct_num = oct(num)
        oct_list = list(oct_num)
        oct_list_2 = oct_list[2:]
        val = ''.join(oct_list_2)

    if(base == 16):
        hex_num = hex(num)
        hex_list = list(hex_num)
        hex_list_2 = hex_list[2:]
        val = ''.join(hex_list_2)

        if val in hex_char_list:
            val = val.upper()

    return val

def print_formatted(number):
    # your code goes here
    width = len(convert(number, 2).format(number))

    for i in range(number):
        print(
            str(i + 1) + width + 
            str(convert(i + 1, 8)) + width + 
            str(convert(i + 1, 16)) + width + 
            str((convert(i + 1, 2)))
            )


if __name__ == '__main__':
    n = int(input())
    print_formatted(n)

你现在得到的输出是什么? - PrinceOfCreation
什么十进制值?像往常一样,这个问题根本不涉及十进制值。在您的方法被调用时,“num”已经是二进制的了。 - user207421
2个回答

3

你的elif是多余的 - 如果你做%2,结果只能是0或1 - 没有必要以不同的方式处理它。


你的代码没有转换整个数字 - 你检查数字的模数,而不是基数(和更高次幂的基数)在其中适合多少次。

你需要获取基数最高可能适合到你的数字。然后你需要知道它适合你的数字多少次,将其从数字中减去并继续执行该操作的余数。你将你的幂缩小一倍,并继续直到你的数字为0。然后你将所有数字累加到一个字符串中。

你修复了你的代码:

def convert(num, base):
    # get the highest power
    power = 0
    while num // (base**(power+1)) > 0:
        power += 1

    # divide, remember, subtract - until down to the lowest power
    result = []
    while num >= 0:
        p = base**power
        if p == 1:
            result.append(num)
            break
        result.append(num // p)
        num -= result[-1]*p
        power -= 1

    return ''.join(map(str,result))

为了获得以下输出:
1 1 1 1
2 2 2 10
3 3 3 11
4 4 4 100
5 5 5 101
6 6 6 110
7 7 7 111
8 10 8 1000
9 11 9 1001
10 12 10 1010
11 13 11 1011
12 14 12 1100
13 15 13 1101
14 16 14 1110
15 17 15 1111
16 20 10 10000

或者您可以使用内置功能:
def make(i):
    for k in range(i+1):
        print(f"{k:>10} {bin(k):>10} {hex(k):>10} {oct(k):>10}")
        # or slice away the prefixes:
        # print(f"{k:>10} {bin(k)[2:]:>10} {hex(k)[2:]:>10} {oct(k)[2:]:>10}")


make(17)

结果为:

         0        0b0        0x0        0o0
         1        0b1        0x1        0o1
         2       0b10        0x2        0o2
         3       0b11        0x3        0o3
         4      0b100        0x4        0o4
         5      0b101        0x5        0o5
         6      0b110        0x6        0o6
         7      0b111        0x7        0o7
         8     0b1000        0x8       0o10
         9     0b1001        0x9       0o11
        10     0b1010        0xa       0o12
        11     0b1011        0xb       0o13
        12     0b1100        0xc       0o14
        13     0b1101        0xd       0o15
        14     0b1110        0xe       0o16
        15     0b1111        0xf       0o17
        16    0b10000       0x10       0o20
        17    0b10001       0x11       0o21

1
或者您可以使用'{i:>#10} {i:>#10b} {i:>#10x} {i:>#10o}'.format(i=k)#请求前缀)。 - Yann Vernier
@Onur 请发布新问题。您原来的问题已经得到了回答。这是一个关于字符串格式化的新问题,与如何创建八进制/二进制/十六进制数字无关。此外 - 我在这里的示例包括使用空格进行格式化。只需计算您最大数字的二进制宽度并相应地进行格式化即可。请参见 https://dev59.com/a2855IYBdhLWcg3wg0nC 和 using-pythons-format-specification-mini-language-to-align-floats - Patrick Artner

1
问题在于你只取数字的模数(num % base),也就是最右边(“最低有效位”)的位。我们想要的不是最低有效位,而是整个分解。

注意:这个问题也适用于所有其他进制(十进制、十六进制...)。

实际上,如果你运行

n = 1000
print_formatted(n)

使用您的函数,您可以得到1000在不同进制下的分解为:

1000 0 8 0

这些都是错误的。

在这里,我提出了一种递归实现:

def convert(integerToConvert, base = 2):
    '''
    When given a num and a base, will get the 
    conversion of that number in that base
    '''

    # The negative integer case is not taken into account
    if (integerToConvert < 0):
        print("ERROR: INTEGER < 0")
        return;

    # When the integer is 0, we know that we are done. There is no more bit
    if (integerToConvert == 0):
        print("WE ARE DONE")
        return;

    # get the current least significant coeff in the integerToEncode
    currentLeastSignificant = integerToConvert % base;
    print(currentLeastSignificant)

    # remove the least significant coeff and start again
    convert((integerToConvert - currentLeastSignificant) / base, base)

我进行了几个快速测试:

convert(17, 2)
1
0.0
0.0
0.0
1.0
WE ARE DONE

convert(16, 2)
0
0.0
0.0
0.0
1.0
WE ARE DONE

convert(17, 16)
1
1.0
WE ARE DONE

NB1: 我打印数字,但您可以将它们存储在您选择的数据结构中。

NB2: 打印时,最高位系数出现在最后(您可以与预期结果进行比较)

NB3: 所有这些计算都有点昂贵,因此如果速度对您很重要,最好的方法实际上是将所有分解存储在数组中并访问它们(常数时间)。


嘿,伙计。我刚看到了你的回答。我因为感激之情给了你一个赞。如果你认为这是一个很好的问题,你能否也给我一个赞呢? - Onur-Andros Ozbek
@OnurOzbek 我已经为这个问题投了赞。希望回答对你有帮助,尽管它可能不如Patrick Artner的高效(我不知道mode的时间复杂度是什么...)。 - GabCaz

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