При решении задач количественного учета в специфических сферах (например, учет криптовалют, микродозирование в химическом производстве или расчеты с микровеличинами) разработчики сталкиваются с необходимостью хранить и обрабатывать числа с точностью более 20 знаков после запятой, а также общей длиной, превышающей стандартные возможности платформы. Рассмотрим подробнее, с какими системными ограничениями 1С приходится иметь дело и как правильно организовать архитектуру базы данных для таких расчетов.
Разберем базовые технические рамки типа данных Число в 1С:Предприятии, которые важно учитывать при проектировании структур данных:
Число. Платформа рассчитывает итоги и обороты на уровне СУБД стандартными числовыми операторами, поэтому использовать строковые данные для автоматического накопления остатков невозможно.Проанализируем основные архитектурные подходы для обхода данных ограничений.
Если суммарная разрядность числа укладывается в 32 знака, но дробная часть содержит 15–20 знаков, наиболее надежным решением является переход на целочисленный учет. Посмотрим, как это устроено на практике.
Вместо хранения дробных величин учет ведется в минимальных неделимых квантах (сатоши, миллиграммы, микросекунды и т.п.). Все входящие значения умножаются на фиксированный масштабный коэффициент 10^N:
Число(32, 0).Посмотрим на пример функции для преобразования масштабированного целого числа в строковое представление с фиксированной точностью:
Функция ПреобразоватьЦелоеВСтрокуСДробью(ЗначениеЦелое, ТочностьДроби)
СтрокаЧисла = Формат(ЗначениеЦелое, "ЧГ=0");
Если СтрДлина(СтрокаЧисла) <= ТочностьДроби Тогда
// Дополняем ведущими нулями дробную часть
СтрокаЧисла = "0." + СтрЗаменить(Прав(Формат(0, "ЧЦ=" + Формат(ТочностьДроби - СтрДлина(СтрокаЧисла), "ЧГ=0")), ТочностьДроби - СтрДлина(СтрокаЧисла)), " ", "0") + СтрокаЧисла;
Иначе
ПозицияТочки = СтрДлина(СтрокаЧисла) - ТочностьДроби;
СтрокаЧисла = Лев(СтрокаЧисла, ПозицияТочки) + "." + Сред(СтрокаЧисла, ПозицияТочки + 1);
КонецЕсли;
Возврат СтрокаЧисла;
КонецФункции
Рассмотрим подход, аналогичный учету курсов валют. Если целая или дробная часть числа слишком мала/велика, вводится дополнительный реквизит Кратность (например, 100, 1000, 1000000):
Количество (с точностью до 10–15 знаков) и целочисленная Кратность.Выясним, как действовать, если общая длина числа (целая часть + дробная часть) превышает 32 знака. Встроенных типов произвольной точности в платформе нет, поэтому стандартный числовой тип применить не удастся.
Строка неограниченной или фиксированной длины (например, Строка(100)).Посмотрим на пример базового поразрядного сложения двух положительных целых чисел, представленных строками произвольной длины:
Функция СложитьДлинныеЧисла(СтрокаА, СтрокаБ)
ДлинаА = СтрДлина(СтрокаА);
ДлинаБ = СтрДлина(СтрокаБ);
МаксДлина = Макс(ДлинаА, ДлинаБ);
Стр1 = Прав("0000000000000000000000000000000000000000" + СтрокаА, МаксДлина);
Стр2 = Прав("0000000000000000000000000000000000000000" + СтрокаБ, МаксДлина);
Результат = "";
Перенос = 0;
Для Индекс = 0 По МаксДлина - 1 Цикл
Поз = МаксДлина - Индекс;
Цифра1 = Число(Сред(Стр1, Поз, 1));
Цифра2 = Число(Сред(Стр2, Поз, 1));
Сумма = Цифра1 + Цифра2 + Перенос;
Перенос = Цел(Сумма / 10);
Результат = Формат(Сумма % 10, "ЧГ=0") + Результат;
КонецЦикла;
Если Перенос > 0 Тогда
Результат = Формат(Перенос, "ЧГ=0") + Результат;
КонецЕсли;
Возврат Результат;
КонецФункции
Таким образом, выбор метода зависит от предельной разрядности: если число укладывается в 32 разряда, оптимально использовать целочисленный учет через Число(32, 0) в регистрах накопления. Если разрядность превышает 32 знака — следует использовать строковое хранение в регистрах сведений с механизмами длинной арифметики.