Одна функция для преобразования десятичных значений в двоичные, шестнадцатеричные и восьмеричные не преобразует в двоичные - PullRequest
3 голосов
/ 21 сентября 2019

Я пытаюсь создать стандартную функцию для преобразования любого десятичного значения в его восьмеричный, шестнадцатеричный и двоичный эквивалент, но по какой-то причине он не работает для двоичного кода.Я попытался ввести дополнительные меры предосторожности в условный оператор для проверки базы 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, чтобы добавить 1 во временный список conv.Затем я преобразовываю список в строку, обращаю его и возвращаю как int.

Например.Если ввод 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)

Ответы [ 2 ]

3 голосов
/ 21 сентября 2019

Ваш 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 голос
/ 21 сентября 2019

Проблема в том, что вы берете только мод вашего номера (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: все эти вычисления немного дороги, так что если скорость имеет значение для васлучше всего хранить все разложения в массивах и получать к ним доступ (постоянное время).

...