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

Я пытаюсь разделить набор чисел на соотношения (32%/68%), но хотел бы иметь алгоритм, чтобы округленные дроби складывались в исходное разделение чисел. Прямой подход этого не делает (22/48 против 23/47).

Qty     32%     68%     Rounded Rounded   Adjusted Adjusted
10      3.2     6.8     3       7         3        7
10      3.2     6.8     3       7         3        7 
5       1.6     3.4     2       3         2        3
5       1.6     3.4     2       3         1        4
10      3.2     6.8     3       7         3        7
10      3.2     6.8     3       7         3        7    
5       1.6     3.4     2       3         2        3    
15      4.8     10.2    5       10        4        11
-------------------------------------------------------------   
70      22.4    47.6    23      47  70    21       49
        22      48 

Гибкость заключается в том, что дробление должно быть как можно ближе к целевому соотношению, если не точное. Итак, если в сумме после округления получается на 1 больше, то ее надо отнять, но от какого числа? Исходное число — 70, что разделяет 22,4/47,6. Так какое соотношение ближе к 32/68 – 22/48 или 23/47? Если 22/48 лучше, то лишнее можно убрать из первого номер одного из отдельных расколов. Но этот мини-сплит должен быть как можно ближе к 32/68. Кажется, что если необходимо внести корректировку, то следует выбрать наибольшее число, чтобы корректировка имела минимальное влияние. Таким образом, 5/10 может быть 4/10, а не 2/3 как 1/4.

Более важным ограничением при суммировании мини-разделений является то, что разделение исходного числа должно быть как можно ближе к 32/68, а исходное число должно быть получено путем сложения мини-разделений.

Возможно ли вообще, что округленные мини-разделения при суммировании будут меньше исходного числа, поэтому вместо того, чтобы что-то убирать, нужно что-то добавить?

Обновлено

Я реализовал предложение Гейба Сечана (большое спасибо!), и сумма скорректированных столбцов дала исходное число. Исходное разделение составляет 21/49, что не ближе к 32/68, чем к 22/48. Но я думаю, что без дальнейшей оптимизации изменения порядка обработки чисел это решение работает.

Если у вас нет гибкости в отношении небольших дроблений, точно соответствующих целевому соотношению, то (в общем) решения нет, как показывает ваш контрпример. Если у вас есть гибкость, пожалуйста, опишите ее. Например, вы бы предпочли минимизировать количество мини-сплитов, измененных с 32/68, или вы бы предпочли минимизировать максимальную абсолютную разницу между любым мини-сплитом и его целевым показателем 32/68, или что-то еще?

Dave 05.04.2024 18:04

Я думаю, что если вы хотите минимизировать абсолютную разницу, вы можете просто математически округлить значения в процентах, потому что невозможно получить ровно 0,5 с целыми числами и соотношением 32/68.

maraca 06.04.2024 02:35

@Дэйв, я отредактировал проблему, чтобы обеспечить гибкость.

Anand 07.04.2024 03:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Отслеживайте ошибку — величину отклонения от округления. Например, если число равно 3,2 и округляется до 3, ошибка равна -.2. Когда ошибка равна 1,6 и округляется до 2, ошибка равна 0,4. При каждом округлении накапливайте ошибку. Когда ошибка станет достаточно большой, откорректируйте округление. Простой способ сделать это — добавить ошибку к фактическому числу, а затем округлить результат. Таким образом, 3,2 с ошибкой 0,6 равно 3,8, которое округляется до 4. Тогда ваша новая ошибка будет -.2 (вы начали с .6, затем добавили -.8, оставив -.2). Однако вы также можете выбрать другие пороговые значения для настройки округления в зависимости от того, насколько вы предпочитаете минимизировать количество корректируемых элементов.

Другие вопросы по теме