Двоичное, десятичное или шестнадцатеричное, давай, братан!

В этой статье мы создадим калькулятор, который можно использовать для преобразования любого числа из любой базы в любую другую. В системах счисления «База» сообщает нам, сколько номеров у вас есть. В двоичном формате 2, в восьмеричном - 8, в десятичном - 10 и т. Д.

Программа, которую мы собираемся написать, может обрабатывать любые number и base, которые мы ей бросаем. Когда мы разберемся с математикой, которая стоит за этим, ее очень легко настроить.

Что мы будем создавать:

Но сначала математика

Этот калькулятор основан на математике (разве не все?). Возможно, нам понадобится освежить память о теории преобразования между базами (или узнать что-то новое).

Если в школе вы изучали математику, основанную на естественных науках, или изучали компьютеры на любом уровне, скорее всего, вы перешли из одной системы счисления в другую. Возможно, вы помните двоичную таблицу или говорите о « десятичной системе», « восьмеричной системе» и «шестнадцатеричная система».

Десятичная система (Base-10) - это та система, которую мы используем ежедневно при счете. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Когда у нас заканчиваются числа, мы добавляем еще одну позицию слева → 10, 11, 12, 13, 14, 15, 16, 17 , 18, 19, 20, 21… и т. Д. Когда числа снова заканчиваются, мы добавляем новую позицию → 100, 101, 102… 118, 119, 120.

Да, да ... Я помню начальную школу ...

Мы не думаем об этом, потому что узнаем это в 2–3 года. Скажите ребенку, чтобы он считал по восьмеричной системе (Base-8), и он, скорее всего, посмотрит на вас несколько секунд, прежде чем вернуться к своей домашней работе на своем iPad. Теория проста и идентична десятичной системе счисления, просто мы к ней не привыкли.

Счет в восьмеричной системе будет выглядеть так:

0,1,2,3,4,5,6,7 → 10,11,12,13,14,15,16,17 → 20,21…

Преобразование одной базы в другую

Первое преобразование, на которое мы должны обратить внимание, - это переход от любой системы счисления (Base-N) к десятичной системе (Base-10). Преобразовать десятичную систему счисления в любую другую систему очень легко. Поэтому важно знать, как перейти к десятичной системе счисления.

Если мы продолжим использовать десятичный и восьмеричный в качестве примеров, мы сможем преобразовать число в восьмеричной системе в его эквивалент в десятичной системе. . Выберем случайное число.

256 (База-8) → ??? (База-10)

(Обещаю, 256 на самом деле было случайным)

  • У нас есть три позиции: 2 (сотни), 5 (десятки) и 6 (единицы). Эти позиции могут занимать от 0 до 7 (8 цифр), как вы помните из вступления.
  • Нам нужно преобразовать каждое из чисел во всех позициях в десятичную систему. В десятичной системе могут храниться 0–9 (10 цифр).

То, как мы это делаем, заключается в том, что мы берем каждое число и умножаем его на базу, рассчитанную на индекс позиции (num * (base ^ position)). Если мы начнем с наименьшего числа вправо, мы умножим 6 на 8⁰, 5 на 8¹ и 2 на 8².

Вот иллюстрация, которая упростит понимание:

Когда у нас есть число в десятичной системе (Base-10), действительно легко перейти к любой системе. Вернемся с 174 (Base-10) к 256 (Base-8)

Мы находим число в другом основании, деля его с основанием, и оставляем остаток. Остальные составят для нас число в другой базе. Когда у нас есть остатки, мы читаем число от наименее значимого числа к наиболее значимому, то есть снизу вверх. Вот и появился ваш новый номер в вашей новой базе! ‍

174/2 дает 21,75. Обратите внимание на то, что 21 красный, а 0,75 зеленый. На следующую строку отправляем 21 и разбираемся с 0,75. Если мы умножим 0,75 на основание, у нас останется остаток (это число, которое мы ищем). Этот номер отправляется в крайнее правое положение синим цветом.

Когда мы достигнем 0, мы официально закончим и можем упаковать чемоданы с красивым номером на нашей новой базе.

Это не только означает, что мы можем перейти от Base-10 к Base-8 и наоборот. Мы можем перейти от Base-X к Base-Y. Любая база, которую мы хотим.

Ощущается что-то вроде этого:

Если вы все еще не уверены, как это работает, я предлагаю проверить «Репетитор по органической химии». Его видео - лучшее, что я знаю на эту тему:



Код

Пришло время погрузиться в код!

Примечание: я делаю большую часть своего программирования вручную. Это означает, что я не использую слишком много библиотек, потому что хочу узнать как можно больше. В этом коде я действительно использую стандартные функции Python, такие как bin(), потому что я хочу показать вам, что это возможно, но вместо использования hex(), я думаю, было интереснее вручную кодировать те же функции. В производственной среде вы, вероятно, захотите сделать ее краткой и использовать библиотеки, которые решают ваши проблемы, вместо того, чтобы кодировать все с нуля.

Эта программа - всего лишь один main.py файл со всем кодом в одном документе. Если хотите, можете продлить это как хотите. Числовой класс? Конечно, почему бы и нет. GUI? Также мы должны кое-что изучить.

Я рекомендую работать с калькулятором базового преобразователя онлайн во время кодирования, чтобы дважды проверить, что ваш код выводит правильные значения.

Вот суть:

Логика кода заключается в том, что мы передаем три аргумента функции convert_number_system():

  • input_number - это число, которое мы хотим преобразовать.
  • input_base - это база, из которой мы хотим преобразовать.
  • output_base - это база, в которую мы хотим преобразовать.

def меню ()

Раньше я не использовал многострочные строки для печати меню, но было бы разумно создать подобное меню.

Функция возвращает всю строку меню, поэтому мы можем использовать ее где угодно. Нам также не нужно беспокоиться о новой строке.

return (
    '''
----------------------------------------------------------
Welcome to the Number Base converter!
The system will ask you for:
- The Number to convert
- What base you want to convert FROM
- What base you want to convert TO
** REMEMBER: All numbers must be integers!(unless HEX) **
----------------------------------------------------------
    ''')

Валидаторы

Вместо того, чтобы проверять ввод пользователя в функции конвертера, я хотел создать валидаторы как функции. Делая это, мы создаем код, который можно использовать повторно.

def validate_bin (check_number):

Эта функция просто проверяет, является ли число действительным двоичным числом.

Мы не хотим проверять длинную строку с несколькими вхождениями одного и того же числа. Если мы конвертируем его в набор, мы удаляем дубликаты. Наборы не могут содержать несколько экземпляров элемента. Мы используем понимание списка, чтобы преобразовать ввод в int и сравнить его с [0,1]

[int(item) for item in set(list(check_number))]

Я решил передавать строки из взаимодействия с пользователем и при необходимости создавать целые числа для ввода. int(item) проверяет, что все числа являются целыми числами (при желании мы могли бы также сравнить строку со строкой (‘0’ , ‘1’)).

Вот как это будет выглядеть за кадром:

‘10010011’[‘1’,’0',’0',’1',’0',’0',’1',’1'][0,1]

если 0 находится в [0,1], это проверяется нормально, если 1 находится в [0,1], это также проверяет штраф. Если бы у вас было число вроде 23, обе цифры не сработали бы, и функция вернула бы False.

def validate_input (check_number):

Ничего особенного… Код проверяет, содержит ли ввод определенные допустимые символы. Мы работаем с числами 0–9, и поскольку мы поддерживаем HEX, мы также включаем a-f в качестве допустимого ввода.

валидатор def (input_number, input_base, output_base):

Эта функция использует другие валидаторы и проверяет все вводимые данные, чтобы мы знали, есть ли смысл в продолжении преобразования.

  • Сначала он проверяет, ввели ли мы число или шестнадцатеричное значение.
  • Затем проверяем базы. Если input_base равно 2, мы преобразуем двоичное число. Следовательно, input_number должен быть только цифрами, и если это так, то он должен быть 0 или 1.
  • Если введены и цифры, и буквы, это шестнадцатеричное число. Если input_base НЕ 16, мы не сможем его преобразовать. HEX - это база-16, и любая другая база будет вычисляться неправильно. Мы могли бы рассмотреть возможность создания предварительно заполненной базы ввода во время взаимодействия, когда кто-то вводит шестнадцатеричное число.
  • Наконец, мы проверяем, пытается ли пользователь преобразовать в Base-1 или из нее. Это невозможно, поэтому вместо сбоя программы мы хотим вернуть ошибку.

Преобразование

Теперь пришло время для основной части кода. Здесь мы применим наши математические навыки. Эта функция выполняет совпадение, которое мы рассмотрели ранее, и имеет несколько шагов безопасности, чтобы убедиться, что мы выводим правильно

def convert_number_system (input_number,…):

remainder_list содержит числа, которые мы хотим вернуть. Если вы помните математику, вы сразу же узнаете остаток ключевого слова.

sum_base_10. Мы хотим использовать Base-10 в качестве промежуточного шага. Мы устанавливаем начальное значение на 0, а затем добавляем все значения, которые мы вычисляем, к этой переменной.

выходной двоичный файл:

if output_base == 2:
    return (bin(input_number)[2:])

Если пользователю нужен двоичный вывод, мы можем использовать встроенную функцию bin (). Нам не обязательно, потому что математика остается неизменной, независимо от того, что мы сдаем, но попробовать это весело.

bin() возвращает 0b и двоичный файл. 0b говорит нам, что это двоичное число. Мы хотим вернуть фактическое число. Вот для чего нужен [2:]. Если вы запустите это в своем терминале, вы увидите разницу:

>>> check_number = 23
>>> print(bin(check_number))
0b10111
>>> print(bin(check_number)[2:])
10111

Он будет печатать, начиная с индекса 2 и далее.

Обратите внимание, что я оставил версию hex () в коде, но закомментировал. Вы можете использовать это, если хотите.

База НЕ равна 10:
Если база не равна 10, мы проходим наш промежуточный шаг. Сначала мы переворачиваем список (вам не обязательно этого делать, но потом вам нужно будет перевернуть индекс в цикле. Мне легче перевернуть список). Обращение списков в Python может быть выполнено с помощью этой фантастической сборки -в коде [:: - 1]

reversed_input_number = input_number[::-1]

hex_helper_dict помогает нам обрабатывать числа выше 9, если пользователь отправил шестнадцатеричный ввод. Если вы помните нашу формулу, мы умножаем числа в каждой позиции на базовый индекс, основанный на позиции.

Здесь снова 256 от восьмеричного до десятичного:

2*(8²) + 5*(8¹) + 6*(8⁰) = 174

Если число шестнадцатеричное, например 23e, на самом деле оно читается как 2, 3, 14.

2*(16²) + 3*(16¹) + 14*(16⁰) = 574

Этот цикл помогает нам со всем этим:

for index, number in enumerate(reversed_input_number):
    for key,value in hex_helper_dict.items():
        if str(number).lower() == key:
            number = value
    sum_base_10 += (int(number)*(int(input_base)**index))

Если вы посмотрите на приведенный выше код, вы увидите, что мы используем как enumerate, так и .items (), чтобы убедиться, что мы можем получить доступ ко всему, что нам нужно для выполнения нашей операции.

Используя enumerate, мы можем получить доступ как к значению, так и к индексу переменной. Когда мы перебираем переменную, мы проверяем, совпадает ли число (например, e) с каким-либо из ключей в словаре. В случае 23e это так, и мы хотим вместо этого установить число 14, чтобы мы могли использовать его для фактических вычислений.

sum_base_10 += (int(number)*(int(input_base)**index))

Теперь, когда мы уверены, что никакие числа не являются буквами, мы можем перебирать числа (оставим 256) и выполнять операции. Для каждого числа, которое мы перебираем, мы выполняем умножение, о котором говорили ранее.

(int (число) * (int (input_base) ** индекс))
6 * (8 ** 0)

Полученные значения добавляются к sum_base_10.

База 10:
Отлично, продолжайте. Мы просто назначаем входной номер sum_base_10:

elif input_base == 10:
    sum_base_10 = int(input_number)

Выполните математические вычисления
Теперь, когда у нас есть значение Base-10, мы можем выполнить деление, чтобы найти остатки и найти новое число.

while sum_base_10 > 0:
    divided = sum_base_10// int(output_base)
    remainder_list.append(str(sum_base_10 % int(output_base))
    sum_base_10 = divided

Нам нужно делить, пока мы не дойдем до 0. Цикл while гарантирует, что мы это сделаем.

Используя деление по этажам //, мы делим число и остаемся с целой частью частного. это означает, что мы переносим только целое число (21), а не то, что стоит после точки (75) на основе нашего примера во вступлении (174/8 = 21,75).

Назначив это число разделенному, мы также можем отправить это значение в sum_base_10 для следующей итерации в конце.

Используя модуль%, мы получим остаток. Он добавляется к Остаточному_листу, чтобы мы могли вывести его позже.

Это цикл while, который продолжается до тех пор, пока мы не нажмем 0.

Если база вывода равна 16
Если база вывода равна 16, это означает, что пользователю нужен шестнадцатеричный вывод. Нам нужно преобразовать любое число больше 9 в букву.

Как и раньше, мы создаем словарь, чтобы облегчить преобразование. Если мы находим совпадение, мы преобразуем число в букву и добавляем его в список.

И наконец:

return ''.join(remainder_list[::-1])

Это меняет местами и превращает наш список в строку, которую мы можем вернуть. Если вы хотите вернуть int, вы можете использовать int (). Убедитесь, что вы учитываете шестнадцатеричные числа, если пользователь запрашивает вывод Base-16.

def execute_converter ():

Фух! Большая часть нашего кода готова.

Последняя часть головоломки - взаимодействие с пользователем. Это простой цикл while, в котором пользователь вводит числа, мы проверяем их и запускаем конвертер, если он проверяет. У пользователя есть возможность делать это столько раз, сколько он хочет.

Мне нравится создавать взаимодействие пользователя с циклами while на основе состояния переменной; вроде proceed у нас здесь. Таким образом, мы можем продолжать работу столько, сколько захочет пользователь.

Имеет два уровня. Первый while инициирует основной цикл на основе proceed.lower() == ‘y’.

Второе объявление valid_input=False, потому что мы хотим проверить все вводимые данные, прежде чем передать их convert_number_system(). Пока ввод False, нам нужен новый ввод. После того, как пользователь вводит данные, запускается валидатор. Если он пройдет, мы можем инициировать convert_number_system()

В конце мы спрашиваем пользователя, хочет ли он снова зайти. Если пользователь набирает «y», мы запускаем код снова. Если он набирает что-нибудь еще, мы выходим из программы.

Альтернативный способ сделать это - попросить пользователя ввести число, которое он хочет преобразовать, или выйти. в переменной number_input.

В заключении

Эта программа охватывает несколько аспектов программирования. Во-первых, нам нужно найти проблему. Проблема в том, что преобразование всех чисел вручную занимает много времени.

Затем мы находим / изучаем математику, чтобы решить проблему и найти общее. Оказывается, мы можем преобразовать что угодно во что угодно с помощью той же формулы. Нам нужно только обрабатывать двоичный и шестнадцатеричный ввод, и нам нужно убедиться, что мы не пытаемся вычислить Base-1. Это означает, что мы можем использовать функции для обработки нашего кода.

Все заключено в меню, взаимодействие с пользователем, а основной код выполнения скрывается в фоновом режиме.

Надеюсь, вы что-то узнали, прочитав это. Если вы обнаружите какие-либо проблемы с кодом или у вас есть другие идеи, сообщите мне. Не стесняйтесь брать код и продолжать развивать его для своих собственных проектов.

-M