К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как найти факториал числа в 1С

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

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

Главная особенность факториала — он растёт очень быстро. Уже 20! равен 2 432 902 008 176 640 000, а 21! превышает 51 квинтиллион. Стандартный тип «Число» в 1С имеет ограниченную точность (до 38 разрядов), поэтому вычислять большие факториалы напрямую нельзя — результат округлится или потеряет точность. Это нужно учитывать до написания кода.

Ниже разобраны практические способы вычисления факториала в 1С: простой цикл, рекурсивная функция, контроль переполнения, а также проверка результата и типичные ошибки. Код подходит для любых конфигураций — от «1С:Бухгалтерии» до самописных решений, поскольку использует только базовые возможности встроенного языка.

Способ 1. Вычисление факториала циклом

Самый надёжный и понятный вариант — итеративный цикл. Создаётся переменная-накопитель, равная 1, и в цикле от 1 до N она последовательно умножается на текущее значение счётчика. Такой код не зависит от глубины стека и легко отлаживается.

Функция Факториал(ЧислоN) Экспорт

Если ЧислоN < 0 Тогда

ВызватьИсключение "Факториал определён только для неотрицательных чисел";

КонецЕсли;

Результат = 1;

Для Сч = 2 По ЧислоN Цикл

Результат = Результат * Сч;

КонецЦикла;

Возврат Результат;

КонецФункции

Обратите внимание на начальное значение: цикл начинается с 2, а не с 1, потому что умножение на единицу ничего не меняет. При N = 0 или N = 1 цикл не выполнится ни разу, и функция вернёт 1 — это математически корректно, так как 0! = 1 и 1! = 1.

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

1c
Результат = 1;
Для Сч = 2 По N Цикл
    Результат = Результат * Сч;
КонецЦикла;
Сообщить("Факториал " + N + " = " + Результат);

Способ 2. Рекурсивная функция

Факториал определяется рекурсивно: N! = N × (N−1)!, поэтому его часто используют как учебный пример рекурсии. В 1С рекурсивные вызовы поддерживаются, и код получается компактным.

Функция ФакториалРекурсия(ЧислоN)

Если ЧислоN <= 1 Тогда

Возврат 1;

КонецЕсли;

Возврат ЧислоN * ФакториалРекурсия(ЧислоN - 1);

КонецФункции

У рекурсии в 1С есть практическое ограничение — глубина стека вызовов. При больших N (сотни и тысячи) платформа аварийно завершит выполнение с ошибкой переполнения стека. Поскольку факториал всё равно теряет точность уже после 20!, на практике это редко становится проблемой, но для продакшен-кода цикл предпочтительнее: он предсказуемее и не расходует стек.

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

Цикл или рекурсия

Цикл (итерация)

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

Рекурсия

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

Ограничение типа «Число» и переполнение

Ключевое ограничение — не алгоритм, а тип данных. Тип «Число» в 1С хранит значения с точностью до 38 разрядов, однако промежуточные вычисления и представление могут округляться раньше, особенно если где-то в цепочке задействованы числа с ограниченной разрядностью. На практике факториалы до 20! вычисляются точно, 21! и выше — уже с потерей точности.

Проверить границу просто: 20! = 2 432 902 008 176 640 000. Если результат вашей функции для 20! совпадает с этим значением — вычисления идут корректно. Для 21! правильный ответ 51 090 942 171 709 440 000, и именно на нём обычно проявляется округление.

Если нужны точные факториалы больших чисел (комбинаторика, вероятностные расчёты), есть два пути. Первый — выносить вычисления во внешнюю компоненту или веб-сервис с поддержкой длинной арифметики. Второй — хранить результат как строку и реализовывать умножение «в столбик» посимвольно, что трудоёмко и редко оправдано.

Где разместить функцию и как её вызвать

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

Если факториал нужен в нескольких местах прикладного решения, вынесите функцию в общий модуль с признаком «Сервер» (и «Вызов сервера», если обращение идёт с клиента). Пометьте её словом Экспорт, чтобы она была доступна извне. Вызов тогда выглядит так: Результат = МойОбщийМодуль.Факториал(10);.

Для управляемых форм помните про контекст: если функция объявлена в модуле формы с директивой &НаСервере, вызывать её из клиентской процедуры напрямую нельзя — потребуется серверный вызов. В толстом клиенте обычных форм такого разделения нет.

Порядок внедрения функции
  1. 1
    Создайте общий модуль или откройте модуль обработки
  2. 2
    Добавьте функцию Факториал с проверкой отрицательного аргумента
  3. 3
    Пометьте функцию словом Экспорт при вызове из других модулей
  4. 4
    Проверьте работу на контрольных значениях: 0!, 5!, 20!
  5. 5
    Убедитесь, что результат 20! равен 2432902008176640000

Проверка результата

Проверять факториал удобно по известным эталонным значениям. Малые числа легко посчитать вручную: 3! = 6, 4! = 24, 5! = 120, 10! = 3 628 800. Граничное значение для точности платформы — 20! = 2 432 902 008 176 640 000.

Удобный приём — сравнение итеративной и рекурсивной версий: обе функции должны давать одинаковый результат на всём допустимом диапазоне. Расхождение означает ошибку в одной из реализаций, чаще всего в граничных условиях (обработка 0 и 1).

Ещё один тест — свойство делимости: N! всегда делится на N без остатка (при N ≥ 1), а также на любое число от 1 до N. Проверка Результат % N = 0 быстро выявляет грубые ошибки вычисления, хотя и не гарантирует абсолютной точности.

Контрольные точки

Как проверить результат

Факториал(0)
Норма

Возвращает 1

Тревожный признак

Возвращает 0 или ошибку

Факториал(5)
Норма

Возвращает 120

Тревожный признак

Любое другое значение — ошибка в цикле

Факториал(20)
Норма

2432902008176640000

Тревожный признак

Округлённое или усечённое значение — проверьте типы

Факториал(-3)
Норма

Вызов исключения с понятным текстом

Тревожный признак

Молча возвращается 1

Типичные ошибки при вычислении факториала

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

Отдельная группа проблем — попытка вычислить факториал дробного числа. Встроенная функция обычно принимает целое, и если извне пришло значение вроде 5,7, поведение зависит от реализации: цикл «По ЧислоN» отработает до ближайшего целого. Лучше явно проверять целостность аргумента или приводить его через Цел() с понятной логикой.

Типичные ошибки
01
Начальное значение результата 0 вместо 1 — произведение всегда обнуляется
02
Отсутствие проверки отрицательного аргумента — функция молча возвращает неверный результат
03
Ожидание точного результата для N больше 20 — тип «Число» теряет точность, ошибка уходит в расчёты
04
Глубокая рекурсия без контроля N — переполнение стека и аварийное завершение
05
Передача дробного числа без приведения — неочевидный результат вычисления

Ещё одна распространённая ситуация — использование факториала в формулах сочетаний C(n, k) = n! / (k! × (n−k)!). Прямое вычисление трёх факториалов быстро упирается в переполнение, хотя сам итоговый результат невелик. В таких случаях формулу упрощают: сокращают множители до вычисления, перемножая только числа от (n−k+1) до n и деля на k!.

Часто задаваемые вопросы

Есть ли в 1С встроенная функция факториала?

Нет, во встроенном языке платформы такой функции нет. Доступны только базовые арифметические операции и функции вроде Цел(), Окр(), Min, Max. Факториал реализуют собственной функцией через цикл или рекурсию — это занимает несколько строк кода.

До какого числа 1С считает факториал точно?

Точные значения гарантированно получаются примерно до 20! включительно (2 432 902 008 176 640 000). Начиная с 21! результат может округляться из-за ограничений разрядности типа «Число». Если нужны бо́льшие точные значения, потребуется длинная арифметика через строки или внешние средства.

Что вернёт функция для нуля?

При корректной реализации — 1, потому что 0! = 1 по математическому определению. Если ваша функция возвращает для нуля другое значение или ошибку, проверьте начальное значение накопителя и границы цикла.

Можно ли вычислить факториал запросом?

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

Как вычислить число сочетаний без переполнения?

Не вычисляйте три факториала по формуле C(n, k) = n! / (k! × (n−k)!) напрямую. Вместо этого перемножьте числа от (n−k+1) до n и последовательно делите на числа от 1 до k — промежуточные значения останутся небольшими, и результат не потеряет точность.

Где лучше разместить функцию факториала в конфигурации?

Если функция нужна в нескольких объектах — в общем модуле с признаком «Сервер». Для разового использования достаточно модуля обработки или формы. Функцию в общем модуле объявляйте с ключевым словом Экспорт, чтобы она была доступна из других модулей конфигурации.

Итог

Что важно запомнить

Готовой функции факториала в 1С нет — напишите свою через цикл с накопителем, начиная с 1. Проверяйте отрицательный аргумент и помните: точный результат тип «Число» даёт примерно до 20!. Проверяйте функцию на контрольных значениях 0!, 5! и 20!.