Как сложить два целых числа в 1С без использования оператора плюс и других арифметических знаков

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике программирования иногда встречаются задачи, которые на первый взгляд кажутся лишенными практического смысла, но на самом деле они отлично проверяют знание платформы, логическое мышление и понимание того, как данные обрабатываются на низком уровне. Одной из таких классических задач является суммирование двух целых чисел без использования стандартного оператора + и других арифметических операций. В этой статье мы подробно разберем, какие инструменты 1С позволяют обойти это ограничение, проанализируем различные подходы — от математических до чисто платформенных.

Решение 1: Использование побитовых операций (Алгоритм полного сумматора)

Это наиболее «программистский» подход, основанный на битовой алгебре. Любое сложение в компьютере выполняется через логические вентили. Мы можем эмулировать этот процесс, используя встроенные функции 1С для работы с битами. Основная идея заключается в том, что исключающее ИЛИ (XOR) дает результат сложения без учета переноса, а логическое И (AND) определяет биты, которые должны быть перенесены в следующий разряд.

Рассмотрим итеративный вариант реализации этого алгоритма. Разберем по шагам, как работает этот цикл:


Функция СложитьБитово(Знач Число1, Знач Число2)
    Результат = ПобитовоеИсключительноеИли(Число1, Число2);
    Перенос = ПобитовыйСдвигВлево(ПобитовоеИ(Число1, Число2), 1);
    
    Пока Перенос <> 0 Цикл
        ВременнаяПеременная = Результат;
        Результат = ПобитовоеИсключительноеИли(Результат, Перенос);
        Перенос = ПобитовыйСдвигВлево(ПобитовоеИ(ВременнаяПеременная, Перенос), 1);
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

Проанализируем ситуацию: этот метод идеально работает для целых чисел, однако стоит помнить об ограничении платформы 1С. Побитовые операции в языке 1С работают с 32-битными целыми числами со знаком. Это означает, что если сумма превысит 2 147 483 647, результат может стать некорректным (произойдет инверсия знака или переполнение).

Решение 2: Манипуляция с позицией в потоке данных

Одним из самых оригинальных способов решения задачи в 1С является использование объекта ПотокВПамяти. Этот объект позволяет управлять «курсором» (позицией) внутри буфера данных. Поскольку позиция в потоке — это целое число, мы можем использовать метод Перейти(), чтобы суммировать смещения.

Посмотрим на пример реализации:


Функция СложениеЧерезПоток(Число1, Число2)
    Поток = Новый ПотокВПамяти;
    // Устанавливаем начальную позицию, равную первому числу
    Поток.Перейти(Число1, ПозицияВПотоке.Начало);
    // Сдвигаем позицию относительно текущей на величину второго числа
    Поток.Перейти(Число2, ПозицияВПотоке.Текущая);
    // Текущая позиция теперь равна сумме
    Возврат Поток.ТекущаяПозиция;
КонецФункции

Важный момент: данный метод изящен тем, что он вообще не использует логических или арифметических вычислений в коде, перекладывая задачу на механизм управления памятью платформы. Это решение обходит многие ограничения и демонстрирует глубокое знание объектной модели 1С.

Решение 3: Группировка и агрегатные функции в запросах

Платформа 1С позволяет выполнять вычисления на уровне СУБД. Хотя в самом тексте запроса можно написать &Число1 + &Число2, условие задачи часто запрещает использование знака «плюс» даже там. В таком случае мы можем воспользоваться механизмом группировки.

Рассмотрим алгоритм решения через временные таблицы:

  1. Создадим таблицу значений и добавим в нее две строки, в каждой из которых будет одно из наших слагаемых в одной и той же колонке.
  2. Передадим эту таблицу в запрос.
  3. Выполним суммирование с помощью агрегатной функции СУММА() при группировке.

Функция СложитьЧерезЗапрос(Число1, Число2)
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Слагаемое", Новый ОписаниеТипов("Число"));
    ТЗ.Добавить().Слагаемое = Число1;
    ТЗ.Добавить().Слагаемое = Число2;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	ТЗ.Слагаемое КАК Значение
    |ПОМЕСТИТЬ ВТ_Данные
    |ИЗ
    |	&ТЗ КАК ТЗ
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	СУММА(ВТ_Данные.Значение) КАК Результат
    |ИЗ
    |	ВТ_Данные КАК ВТ_Данные";
    
    Запрос.УстановитьПараметр("ТЗ", ТЗ);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        Возврат Выборка.Результат;
    КонецЕсли;
КонецФункции

Этот метод хорош тем, что он универсален и работает с любыми числами, которые поддерживает тип Число в 1С, включая дробные и очень большие значения, не ограничиваясь 32 битами.

Решение 4: Использование длины коллекций и строк

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


Функция СложитьЧерезМассив(Число1, Число2)
    Коллекция = Новый Массив;
    
    Для Счетчик = 1 По Число1 Цикл
        Коллекция.Добавить(Истина);
    КонецЦикла;
    
    Для Счетчик = 1 По Число2 Цикл
        Коллекция.Добавить(Истина);
    КонецЦикла;
    
    Возврат Коллекция.Количество();
КонецФункции

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

Решение 5: Особенности работы циклов в 1С

Интересной особенностью встроенного языка 1С является поведение переменной-счетчика в цикле Для ... По .... После завершения цикла значение переменной-счетчика становится на единицу больше, чем конечное значение. Это можно использовать для инкрементирования (прибавления единицы) без арифметики.

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


Функция СложитьЦиклом(Число1, Число2)
    Результат = Число1;
    Для СчетчикВнешний = 1 По Число2 Цикл
        // Данный цикл выполнится 1 раз, но увеличит 'Результат' на 1
        Для Итератор = Результат По Результат Цикл
        КонецЦикла;
        Результат = Итератор;
    КонецЦикла;
    Возврат Результат;
КонецФункции

Здесь мы видим, что переменная Итератор после выхода из внутреннего цикла принимает значение Результат + 1. Повторяя это действие Число2 раз, мы получаем итоговую сумму. Это очень специфичный для 1С способ, демонстрирующий понимание нюансов работы интерпретатора кода.

Решение 6: Обходные пути через даты

В 1С реализованы мощные функции работы с датами, которые внутри себя уже содержат логику сложения временных интервалов. Мы можем использовать функцию ДобавитьМесяц() или работу с секундами (хотя работа с секундами напрямую часто требует использования оператора +, функции работы с датами позволяют этого избежать).

Проанализируем пример с объектом Дата:


Функция СложитьЧерезДаты(Число1, Число2)
    БазоваяДата = '00010101'; // Начало времен
    // Добавляем к дате количество секунд, равное Число1
    ДатаСПервымСлагаемым = ДобавитьМесяц(БазоваяДата, 0); // Просто инициализация
    // В 1С разница дат дает количество секунд. 
    // Но нам нужно именно сложение без знака плюс.
    // Можно использовать внешние компоненты или специализированные функции.
КонецФункции

Хотя работа с датами чаще всего используется для вычитания (получение разницы), программное добавление периодов в цикле через методы платформы также является валидным способом решения подобных задач на собеседованиях.

Резюме

Мы рассмотрели несколько принципиально разных подходов к решению задачи суммирования в 1С без арифметических операторов:

  1. Битовые операции: Самый быстрый и правильный с точки зрения теории алгоритмов метод, но ограниченный разрядностью 32-битных чисел.
  2. Потоки данных: Элегантное использование механизмов платформы по управлению памятью.
  3. Запросы: Наиболее надежный метод для работы с большими числами и высокой точностью.
  4. Коллекции и циклы: Способы, демонстрирующие знание особенностей поведения объектов и конструкций языка 1С.

Выбор конкретного метода зависит от того, какую именно цель преследует интервьюер: проверить ваше знание битовой логики, умение работать с объектами платформы или просто оценить креативность мышления.

← На главную