Как исключить нули при перемножении чисел в 1С

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

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

Метод 1: Универсальный обход массива в цикле

Самым надежным и понятным способом является использование цикла. Этот метод идеально подходит, когда количество множителей заранее неизвестно или может меняться. Рассмотрим алгоритм, который не просто умножает числа, но и ведет учет количества значащих (ненулевых) элементов.

Проанализируем следующий программный код:


Функция РассчитатьПроизведениеБезНулей(МассивЧисел)
    Произведение = 1; 
    СчетчикНенулевых = 0;

    Для каждого ТекущееЧисло Из МассивЧисел Цикл
        Если ТекущееЧисло <> 0 Тогда
            Произведение = Произведение * ТекущееЧисло;
            СчетчикНенулевых = СчетчикНенулевых + 1;
        КонецЕсли;
    КонецЦикла;

    // Если ни одно число не было умножено (все нули), возвращаем 0
    Возврат ?(СчетчикНенулевых = 0, 0, Произведение);
КонецФункции

Почему это работает: Мы инициализируем переменную Произведение единицей. Если мы встретим число 5, результат станет 5. Если встретим 0, мы его просто пропускаем. Использование переменной СчетчикНенулевых позволяет нам отличить ситуацию, когда результат равен 1 из-за перемножения единиц, от ситуации, когда в массиве вообще не было подходящих чисел.

Метод 2: Использование краткой формы условия для фиксированных переменных

Бывают случаи, когда количество переменных строго ограничено (например, Ч1, Ч2, Ч3). В такой ситуации использование цикла может показаться избыточным. Разберем, как можно записать расчет в одну строку, используя тернарный оператор ?().

Рассмотрим пример реализации для трех переменных:


// Проверяем, что хотя бы одно число не равно нулю через сумму (для положительных чисел)
К1 = ?(Ч1 + Ч2 + Ч3 = 0, 0, ?(Ч1 = 0, 1, Ч1) * ?(Ч2 = 0, 1, Ч2) * ?(Ч3 = 0, 1, Ч3));

Выясним причину использования вложенных условий. Внутренние операторы ?(Ч = 0, 1, Ч) подменяют ноль на единицу, чтобы при умножении значение не изменилось. Внешнее условие ?(Сумма = 0, 0, ...) служит предохранителем: если все переменные нулевые, результат принудительно обнуляется.

Важное замечание: Будьте осторожны с проверкой через сумму Ч1 + Ч2 + Ч3 = 0. Если в ваших данных могут присутствовать отрицательные числа (например, 5 и -5), их сумма даст ноль, и алгоритм отработает неверно. В таком случае безопаснее использовать функцию Макс():


К1 = ?(Макс(Абс(Ч1), Абс(Ч2), Абс(Ч3)) = 0, 0, ?(Ч1 = 0, 1, Ч1) * ?(Ч2 = 0, 1, Ч2) * ?(Ч3 = 0, 1, Ч3));

Метод 3: Динамическое вычисление выражения через функцию Вычислить()

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

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


СтрФормата = "ЧРД=.; ЧН=1; ЧГ=";
ТекстВыражения = СтрШаблон("%1 * %2 * %3", 
    Формат(Ч1, СтрФормата), 
    Формат(Ч2, СтрФормата), 
    Формат(Ч3, СтрФормата));

Результат = Вычислить(ТекстВыражения);

В данном примере параметр формата ЧН=1 (представление нуля) заменяет число 0 на строку "1". Это элегантный способ «обмануть» математику при вычислении строки. Однако помните, что этот метод требует дополнительной проверки на случай, если абсолютно все входящие значения были нулевыми.

Метод 4: Работа с большими массивами данных через Таблицу значений

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

Разберем по шагам:

  1. Загружаем данные в объект ТаблицаЗначений.
  2. Используем метод НайтиСтроки() с отбором, где значение не равно 0.
  3. Если полученный массив строк пуст — результат 0.
  4. Если не пуст — перемножаем только отобранные значения.

// Пример логики
Отбор = Новый Структура("ЗначениеКоэффициента", 0);
СтрокиСНулями = ТЗ_Данных.НайтиСтроки(Отбор);
// В реальной задаче эффективнее отобрать НЕ нули, либо просто 
// перебрать таблицу, пропуская итерации с 0.

Сравнение подходов и рекомендации

Проанализируем ситуацию: какой метод выбрать в конкретном случае?

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

← На главную