Подбор слагаемых для нужной суммы

24.01.25

Разработка - Математика и алгоритмы

Цель публикации - объяснение простого надежного метода, который вы можете применить на практике.

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Подбор слагаемых для нужной суммы:
.epf 9,95Kb
6 1 850 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

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

Цель публикации - объяснение метода на практическом примере, чтобы читатель мог его понять и самостоятельно воспроизвести. Кому этого недостаточно - реализация метода во внешней обработке в приложении к публикации.

 

Вводные данные:

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

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

Необходимо разработать механизм формирования такой выборки товаров.

У задачи "получить из набора слагаемых максимально приближенную к заданному числу сумму" есть несколько способов решения, её еще называют "Задача о сумме подмножеств" (см. статью на Википедии).

 

Рассмотрим один из способов:

N={х1, x2, x3, x4, x5...} - список слагаемых. В данном примере это себестоимость товаров.

R - Число, к которому стремится, не превышая, сумма слагаемых из списка N. 

 

Шаги решения:

1. Создать список F, первоначально состоящий из одного элемента, равного 0.

2. Для каждого элемента x из списка N:

Записать в конец списка F элементы, полученные из списка F, путем увеличения каждого его элемента на величину x, где x - значение текущего элемента из списка N.

3. Отсортировать элементы списка F в порядке возрастания.

4. Удалить из списка F все элементы, больше X.

5. Последний элемент из списка F является решением задачи.

 

Пример:

Красным - отмечены добавляемые на каждом шаге в конец списка числа

n - порядковый номер элемента из списка N, в расчетах не участвует.

N= {4.1, 3.2, 5.5, 7, 6.3};  R = 13.4;

1. F= {0}

2.1 n=1; х = 4.1; F= {0, 4.1}

2.2 n=2; х = 3.2; F= {0, 4.1, 3.2, 7.3}

2.3 n=3; х = 5.5; F= {0, 4.1, 3.2, 7.3, 5.5, 9.6, 8.7, 12.8}

2.4 n=4; х = 7,0; F= {0, 4.1, 3.2, 7.3, 5.5, 9.6, 8.7, 12.8, 7, 11.1, 10.2, 14.3, 12.5, 16.6, 15.7, 19.8}

2.5 n=5; х = 6.3; F= {0, 4.1, 3.2, 7.3, 5.5, 9.6, 8.7, 12.8, 7, 11.1, 10.2, 14.3, 12.5, 16.6, 15.7, 19.8, 6.3, 10.4, 9.5, 13.6, 11.8, 15.9, 15, 19.1, 13.3, 17.4, 16.5, 20.6, 18.8, 22.9, 22, 26.1}

3. F= {0, 3.2, 4.1, 5.5, 6.3, 7, 7.3, 8.7, 9.5, 9.6, 10.2, 10.4, 11.1, 11.8, 12.5, 12.8, 13.3, 13.6, 14.3, 15, 15.7, 15.9, 16.5, 16.6, 17.4, 18.8, 19.1, 19.8, 20.6, 22, 22.9, 26.1}

4. F= {0, 3.2, 4.1, 5.5, 6.3, 7, 7.3, 8.7, 9.5, 9.6, 10.2, 10.4, 11.1, 11.8, 12.5, 12.8, 13.3}

5.  13.3

 

Для того, чтобы  получить список слагаемых, из которых получилось результирующее число, можно для каждого элемента списка F хранить набор слагаемых. Тут возможны разные варианты, в своём примере  я использовал СписокЗначений.

Пример под публикацией был написан для УТ 10.3 в режиме совместимости 8.3.6 и выше (Обычное приложение)

Как работает обработка (см. рисунок формы): 

1. Заполняем "Дата", "Склад", "Сумма себестоимости"

2. По кнопке "Заполнить" заполняется табличная часть на форме, и в ней отмечаются строки с подобранными слагаемыми наиболее близко подходящие к сумме себестоимости.

3. По кнопке "Создать реализацию", соответственно создается реализация, которая заполняется из отмеченных на форме строк. 

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Математика и алгоритмы Программист 1С 8.3 Абонемент ($m)

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

1 стартмани

07.11.2025    4493    12    InFlach    17    

25

Математика и алгоритмы Программист 1С:Предприятие 8 1C:Бухгалтерия Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    12798    stopa85    12    

43

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    20060    user1959478    57    

40

Математика и алгоритмы Разное 1С:Предприятие 8 1C:Бухгалтерия Россия Абонемент ($m)

Расширение (+ обработка) представляют собою математический тренажер. Ваш ребенок сможет проверить свои знание на математические вычисление до 100.

2 стартмани

29.09.2023    12212    maksa2005    8    

27

Математика и алгоритмы Инструментарий разработчика Программист 1С:Предприятие 8 Россия Абонемент ($m)

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

1 стартмани

09.06.2023    20365    11    SpaceOfMyHead    20    

65

Математика и алгоритмы Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Три задачи - три идеи - три решения. Мало кода, много смысла. Мини-статья.

03.04.2023    13721    RustIG    9    

30

Механизмы платформы 1С Математика и алгоритмы Программист 1С:Предприятие 8 Россия Бесплатно (free)

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

23.11.2022    12821    gzharkoj    15    

27

Математика и алгоритмы Программист 1С:Предприятие 8 Россия Абонемент ($m)

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

1 стартмани

21.03.2022    11855    8    kalyaka    11    

45
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. starik-2005 3207 22.01.24 13:24 Сейчас в теме
Пока у нас слагаемых немного (допустим, до 20) - это не так и долго работает. Но длина массива уже 2^20 ~ 1 000 000. При длине массива в 30 слагаемых у нас уже миллиард с лишним элементов в массиве. А если у нас сотня слагаемых?
2. Johnson1987 29 23.01.24 06:19 Сейчас в теме
(1) Это правда. Но мне удалось получить достаточно точный результат, используя этот метод и творческий подход. Используя массив до 20 слагаемых
3. starik-2005 3207 23.01.24 10:30 Сейчас в теме
(2)
Используя
Ну, предположу, можно отсечь все, что больше или сумма чего больше, чем требуемая. Но это вряд ли поможет в настоящих ситуациях, когда сумма значительно больше любого слагаемого.
В принципе, здесь нет необходимости хранить суммы - можно просто хранить максимальный результат, но придется каждый раз суммировать элементы заново, хотя это и не должно увеличить количество итераций. Но 2^100 - это ну очень много. Как вариант решения можно рассмотреть алгоритм рюкзака, но он тоже займет какое-то количество памяти. При творческом подходе это количество можно сократить до искомой суммы, деленной на наименьший общий делитель слагаемых, ну или рассчитать до рублей, но длина массива на элемент будет равна количеству рублей. Ну там можно и еще покреативить и сделать динамический индекс и т.д. - народ, предположу, такие штуки мутит.
Для отправки сообщения требуется регистрация/авторизация