Привет, Хабр! Когда-то совсем недавно я, (пока что) зеленый джун, узнал о таком интересном языке, как 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

Если вдруг не дошло

Значение (расшифровка)

>

x++

Как переключать вкладки в браузере на Ctrl+Tab

Переместить указатель вправо на 1 единицу

<

x--

Как переключать вкладки на Ctrl+Shift+Tab

Переместить указатель влево на 1 единицу

+

tape[pointer] += 1

Как кнопка ▲ на пульте

Увеличивает значение в текущей ячейке на 1

-

tape[pointer] -= 1

Как кнопка ▼ на пульте

Уменьшает значение в текущей ячейке на 1

.

print()

Вывод на дисплей

Вывод значения в ячейке

,

input()

Сканер штрих-кода

Ввод значения и сохранение его ASCII-кода

[

while memory[pointer] != 0:

"Пока не съешь суп..."

Начало цикла

]

конец блока while

"...не получишь десерт!"

Конец цикла

Синтаксис же этого чудо-языка выглядит так:

>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-] <.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.>++++++++++.

Все это - код. И даже точка в конце. Выводит, кстати, "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, но для меня это задание даже не со звездочкой, а по меньшей мере с факториалом. Энтузиасты..?

Комментарии (6)


  1. Tishka17
    16.01.2026 16:13

    Если у вас калькулятор на brainfuck, почему большая часть вычислений написна на питоне?


    1. nulovkin
      16.01.2026 16:13

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


  1. aborouhin
    16.01.2026 16:13

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

    С чего бы это на Тьюринг-полном языке уже даже и калькулятор не написать?.. Как-то так.


  1. Tzimie
    16.01.2026 16:13

    А что, в питоне есть х++ ?


    1. nulovkin
      16.01.2026 16:13

      Не, в питоне придется писать x += 1, а что, где вы тут такое увидели?


      1. Tzimie
        16.01.2026 16:13

        В таблице. Колонка "аналог на питон"

        Вторая колонка