Привет, Хабр! Когда-то совсем недавно я, (пока что) зеленый джун, узнал о таком интересном языке, как Brainfuck. Даже не языке, а так, "язычке", с 8 командами. 8-битные лимиты чисел (т.е. не может обрабатывать числа больше 255), а синтаксис и процесс кодинга такой, что и тимлид там ногу сломит. Увидев сие чудо 1993 года (динозавер), меня постигла безумнейшая идея провести один веселый вечер за компов, породив полноценный калькулятор, использовав BF-код для вычислительных мощей в своей забавной разработке. Но сначала давайте по порядку...
Что вообще за Brainfuck такой?
"Brainfuck — один из эзотерических языков программирования, придуман Урбаном Мюллером (нем. Urban Müller) в 1993 году, известен своим минимализмом. Название языка можно перевести на русский как вынос мозга (англ. brainfuck). Язык имеет восемь команд, каждая из которых записывается одним символом. Исходный код программы на Brainfuck представляет собой последовательность этих символов без какого-либо дополнительного синтаксиса.
Одним из мотивов Урбана Мюллера было создание языка с как можно меньшим компилятором. Отчасти он был вдохновлён языком FALSE, для которого существовал компилятор размером 2044 байта. Существуют компиляторы языка Brainfuck размером меньше 200 байт." - гласит Википедия.
У Brainfuck, в отличие от бескрайних C, Python, Java и прочих, всего 8 команд (или функций, если вам так по душе). И их стиль тоже не ахти:
BF-код |
Аналог на Python |
Если вдруг не дошло |
Значение (расшифровка) |
|
|
Как переключать вкладки в браузере на |
Переместить указатель вправо на 1 единицу |
|
|
Как переключать вкладки на |
Переместить указатель влево на 1 единицу |
|
|
Как кнопка ▲ на пульте |
Увеличивает значение в текущей ячейке на 1 |
|
|
Как кнопка ▼ на пульте |
Уменьшает значение в текущей ячейке на 1 |
|
|
Вывод на дисплей |
Вывод значения в ячейке |
|
|
Сканер штрих-кода |
Ввод значения и сохранение его ASCII-кода |
|
|
"Пока не съешь суп..." |
Начало цикла |
|
конец блока |
"...не получишь десерт!" |
Конец цикла |
Синтаксис же этого чудо-языка выглядит так:>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]
<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.>++++++++++.
Все это - код. И даже точка в конце. Выводит, кстати, "Hello, World!". Более того, в этой разработке, явно предназначавшейся для древних аннунаков, еще нельзя выходить за переделы 28 (то есть, 256). Не уследил и вышел за грани допустимого? Тогда твоя программа просто сделает так, выражаясь общедоступным языком под названием Python:tape[pointer] % 256
Ваше значение просто уйдет в ноль. Если было 257 - станет 1. Ну и так далее. Из-за этой особенности, я очень сомневаюсь, что на чистом BF можно написать полноценный калькулятор для работы с большими числами. Но если способ есть, дайте знать.
"Но ты же калькулятор обещал, гони его сюда"
Хорошо, хорошо. Как я уже сказал, нет (или я просто не вижу) способа написать полноценный калькулятор на BF. А даже если бы и был, я бы такой фигней не стал страдать. Но что помешало бы мне обернуть чистый BF в Python-оркестратор и использовать его для вычислительных мощей?
Сначала я занялся интерпретатором BF-кода. Написал я его опять же на Python, сделав его в случае чего независимым. Благодаря этому, любой сможет вживить его в свой проект.
BF-составляющая кода была жесточайше порублена на 5 модулей и растасована по файлам директории bf_modules/. Сам же BF-код выглядел примерно так (функция сложения):
,
> ,
< [->+<]
> .
Выглядит просто? А вот вам возведение в степень (по факту цикличное умножение - до чего же тривиален этот язык):
,
> ,
< [->>+<<]
>> [->+<]
< [
> [->>+<<]
>> [->+<]
< [
->>+<<
>> [->+<<+>]
< [->>+<<]
>> [->+<]
<< -
]
>> [-<<+>>]
<< -
]
>> [-<<+>>]
<< .
Когда с модулями и интерпретатором было покончено, я взялся за сам оркестратор. Вот тогда я и столкнулся с лимитом значений в 255. Чтобы его обойти, мне пришлось хитрить и реализовывать 256-ричную систему счисления:
def _split_to_cells(number):
"""Split a number into base-256 cells"""
if number == 0:
return [0]
n = abs(number)
cells = []
while n > 0:
cells.append(n & 0xFF) # n % 256
n >>= 8 # n // 256
return cells
Позже я основал функции для обработки больших чисел. Работали они как-то так:
def _add_big_numbers(self, a_cells, b_cells):
"""Сложить большие числа"""
result = []
carry = 0
max_len = max(len(a_cells), len(b_cells))
for i in range(max_len):
a_val = a_cells[i] if i < len(a_cells) else 0
b_val = b_cells[i] if i < len(b_cells) else 0
total = a_val + b_val + carry
if total >= 256:
total -= 256
carry = 1
else:
carry = 0
result.append(total)
if carry:
result.append(1)
# Удаляем ведущие нули
while len(result) > 1 and result[-1] == 0:
result.pop()
return result
def _subtract_big_numbers(self, a_cells, b_cells):
"""Вычесть большие числа"""
# Check if result will be negative
a_int = self._cells_to_number(a_cells)
b_int = self._cells_to_number(b_cells)
if a_int < b_int:
# Brainfuck не поддерживает негативные числа =(
return [0]
result = []
borrow = 0
max_len = max(len(a_cells), len(b_cells))
for i in range(max_len):
a_val = a_cells[i] if i < len(a_cells) else 0
b_val = b_cells[i] if i < len(b_cells) else 0
diff = a_val - b_val - borrow
if diff < 0:
diff += 256
borrow = 1
else:
borrow = 0
result.append(diff)
# Удаляем ведущие нули
while len(result) > 1 and result[-1] == 0:
result.pop()
return result
(Пока редактировал код, случайно нажал Ctrl+S. По привычке.)
После модулей я принялся за само исполнение операций.
def _execute_big_operation(self, op, a, b):
"""Execute operation with big numbers"""
# Convert numbers to cells
a_cells = self._split_to_cells(a)
b_cells = self._split_to_cells(b)
# Execute operation
if op == '+':
result_cells = self._add_big_numbers(a_cells, b_cells)
elif op == '-':
result_cells = self._subtract_big_numbers(a_cells, b_cells)
elif op == '*':
result_cells = self._multiply_big_numbers(a_cells, b_cells)
elif op == '/':
result_cells = self._divide_big_numbers(a_cells, b_cells)
elif op == '^':
result_cells = self._power_big_numbers(a_cells, b_cells)
else:
raise ValueError(f"Unsupported operation: '{op}'")
# Convert back to number
return self._cells_to_number(result_cells)
Все последующие модули отвечали за парсинг выражения, да и в целом углублялись в абстрактную логику. Вам будет неинтересно копаться там, верно? Если вы захотите сами узнать, как там все происходит - ссылку на репу я оставил в конце статьи.
Дальше оставался только main.py, который в основном отвечал за UI и пару параметров для запуска. Так, если вы запустите его через команду python main.py --8bit (или python3 main.py --8bit, если вы любитель Linux), то благодаря этой части:
import argparse
# ...
def main():
parser = argparse.ArgumentParser(
description='Brainfuck Calculator',
epilog='Example: python main.py "999+999" "1000*500"'
)
# ...
parser.add_argument(
'--8bit',
dest='force_8bit',
action='store_true',
help='Use 8-bit mode (for testing only)'
)
...вы сможете испытать полный и незацензуренный BF. Все операции не будут превышать 255 в результатах. Например:
Mode: 8-bit (results modulo 256)
Supported operations: +, -, *, /, ^
Enter 'help' for help, 'quit' to exit
> 55+55
= 110
> 55*55
= 165
При нормальном же запуске он за милу душу будет выполнять такие операции, как 999^2 (будет 998001), или же 123456789*10 (будет 1234567890). Поддерживает только такие операнды, как +, -, *, / и ^. В будущем планирую добавить факториал (статья написана на момент 11.01.2026, калькулятор же разработан 15.12.2025).
Подведем итоги
Даже такой цифровой калека, как Brainfuck, может быть использован для вычислительных операций. Но даже это требует экзоскелета в виде Python. На гитхабе самого BF-кода там всего-то 2.2%, остальные 97.8% занимает Python. Но при этом в одном репо там еще и интерпретатор, который был создан и помещен туда исключительно за компанию. Обязательно рекомендую скачивать его вместе с оркестратором - они очень тесно связаны. Сам же репо: https://github.com/garantiatsverga/brainfuck_calculator
P.S. Помимо этого, я еще посчитал, что интерпретатор на Python - не лучшая идея. Очень уж руки чешутся переписать его на C, но для меня это задание даже не со звездочкой, а по меньшей мере с факториалом. Энтузиасты..?
Tishka17
Если у вас калькулятор на brainfuck, почему большая часть вычислений написна на питоне?
nulovkin
Я думаю, питон лучше подходит чтобы писать и читать на нем. Лично я на эти восемь символов уже нагляделся в первой половине статьи, стена визуально-бессмысленного текста много бы не привнесла.
Я ознакомился с репо, похоже автор написал интерпретатор брейнфака на питоне - брейнфак занимается только самими математическим операциями (смешно, обычно это высокоуровневые языки написаны на низкоуровневых).