Почему обнуляются знаки после запятой в регистрах накопления 1С и как сохранить точность до 10 знаков?

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

При разработке специфических систем учета в 1С (например, при работе с высокоточными величинами или криптовалютами) разработчики часто сталкиваются с необходимостью хранить дробные числа с точностью до 10 знаков после запятой. Однако при создании ресурса регистра накопления с типом Число(20,10) происходит неприятное поведение: движения по регистру записываются корректно, а при запросе остатков платформа возвращает ноль в последних разрядах (например, вместо 0,0000000001 выводится 0,0000000000).

В этой статье мы подробно разберем причину такого поведения СУБД и платформы 1С, а также рассмотрим несколько способов решения этой задачи.

Выясняем причину проблемы: особенности СУБД и расчет итогов

Рассмотрим, что происходит на уровне системы управления базами данных (СУБД MS SQL Server или PostgreSQL) при проведении документа и расчете остатков по регистру накопления:

  1. Максимальная суммарная разрядность числового типа DECIMAL в СУБД и в платформе 1С составляет 38 знаков.
  2. При вычислении итогов регистра накопления платформа генерирует фоновые SQL-запросы с использованием агрегатной функции SUM.
  3. Чтобы избежать переполнения при суммировании, СУБД автоматически увеличивает разрядность результата. По правилам MS SQL Server, если общая разрядность промежуточного выражения превышает 38 знаков, СУБД гарантирует сохранение целой части числа, но начинает принудительно обрезать (усекать) дробную часть.
  4. При типе ресурса Число(20,10) с учетом автоматического запаса СУБД под суммирование итоговая разрядность превышает лимит в 38 знаков. В результате СУБД сбрасывает точность дробной части с 10 до 8 знаков, из-за чего сверхмалые значения (такие как 0,0000000001) теряются и обнуляются при пересчете таблиц итогов.

Решение 1. Оптимизация разрядности ресурса в конфигураторе

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

Проанализируем пример: если задать типом ресурса Число(14,10) вместо Число(20,10), то суммарная длина числа составит 24 знака. Это оставляет СУБД необходимый запас разрядности при выполнении операции SUM в пределах допустимого лимита (38 знаков).

Разберем по шагам действие разработчика:

  1. Откроем конфигуратор и перейдем к ресурсу регистра накопления.
  2. В поле типа установим Длина = 14, Точность = 10.
  3. Сохраним конфигурацию базы данных и выполним пересчет итогов регистра.

Важное замечание: при увеличении целой части до Число(15,10) или Число(16,10) десятый знак после запятой снова начнет срезаться при проведении документов и обновлении итогов, поэтому значение длины 14 является оптимальным лимитом для точности 10 знаков.

Решение 2. Хранение значений с коэффициентом (целочисленный учет)

Если для бизнес-логики одновременно требуются и большие значения целой части, и высокая точность дробной, стандартное ограничение типов СУБД можно обойти архитектурно. Для этого используется учет в целых числах с определенным множителем.

Рассмотрим принцип работы этого метода:

  1. В регистре накопления создается ресурс с типом Число(38,0) или Число(20,0) без дробной части.
  2. При записи движения исходное значение умножается на коэффициент $10^{10}$ (10 000 000 000).
  3. При получении данных из регистра остаток делится на этот же коэффициент.

Посмотрим на пример вычисления повышенной точности в запросе 1С:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВЫРАЗИТЬ(13.1 / 13 КАК ЧИСЛО(27, 25)) КАК Точность";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    Сообщить(Строка(Выборка.Точность));
КонецЕсли;

Решение 3. Использование приведения типов ВЫРАЗИТЬ в запросах

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

Проанализируем конструкцию запроса с явным управлением разрядностью:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВЫРАЗИТЬ(СУММА(Регистр.Количество) КАК ЧИСЛО(24, 10)) КАК КоличествоОстаток
    |ИЗ
    |	РегистрНакопления.МойРегистр КАК Регистр";

Использование ВЫРАЗИТЬ с явным указанием длины 24 и точности 10 заставляет СУБД сохранять требуемый масштаб при агрегации данных.

Рекомендации по настройке отображения в отчетах

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

Чтобы убедиться, что отчёт отображает все 10 знаков после запятой:

  1. В настройках поля СКД перейдем в свойство Оформление -> Формат.
  2. Зададим строку формата: ЧДЦ=10; ЧН=0 (где ЧДЦ — число знаков дробной части).
  3. На формах документов и элементов укажем аналогичный формат в свойствах элементов управления.
← На главную