Как я понимаю, у нас есть куча неотрицательных значений с плавающей точкой между 0 и 1, которые составляют 1, и мы хотим округлить каждое до двух десятичных разрядов, не меняя тот факт, что они составляют 1.
Во-первых, масштабируйте числа в 100 раз, чтобы у нас были x_1, ..., x_n, которые в сумме равны 100. Теперь нам нужно округлить их до целых чисел, чтобы они по-прежнему суммировались до 100.
Давайтезапишите frac (x) для дробной части x, которая может быть вычислена как x - int (x).Обратите внимание, что 0 <= frac (x) <1. </p>
Сначала рассмотрим сумму дробных частей frac (x_1) + frac (x_2) + ... + frac (x_n).Это значение является целым числом от 0 до n-1.Давайте назовем F. Простой способ вычислить F так: 100 - (int (x_1) + ... + int (x_n)).(Это также может быть самый простой способ увидеть, что сумма дробных частей представляет собой целое число!)
Небольшая мысль должна убедить вас, что это целое число F - количество раз, которое вам нужно округлить, иследовательно, nF - это количество раз, которое вам нужно округлить.Следовательно, отсортируйте ваш исходный список от наименьшего к наибольшему по дробной части, затем округлите число первых nF и округлите число последних F.
Например, если у нас есть числа 1/7, 1/6, 8/42, 1/10, 1/11, 34/110 (да, сумма равна 1), мы умножаем на 100 изапишите в десятичном виде: 14,2857, 16,66666, 19,047619, 10, 9,090909, 30,90909.Целые части: 14, 16, 19, 10, 9, 30, что в сумме равно 98. Это означает, что F = 2, nF = 4.Сортировка чисел по дробным частям дает: 10, 19,047619, 9,090909, 14,2857, 16,66666, 30,90909.Так как F = 2 и nF = 4, округляем последние два и округляем первые четыре.В этом примере этот метод эквивалентен округлению до ближайшего, но, конечно, он не всегда будет работать таким образом!