将浮点数转换为具有给定总和的整数

Convert floats to ints with given sum

我想将浮点数组转换为整数数组。整数应总和为给定值,并且它们的值应类似于缩放输入数组。

也就是说,完美的结果是由input_float / sum_of_floats * target_sum计算出来的。示例:给定浮点数 0.1, 0.2, 0.5 和目标总和 16,输出应为 2, 4, 10

可悲的是,这些数字在现实中并不是那么好,所以我希望与实值相比,将误差最小化,完美的结果。

例如,如果目标是 17,则应该是 2, 4, 11。第一个浮点数转换为 0.1 / 0.8 * 17 = 2.125。第二个和第三个对应 4.2510.6。显然,10.6 应该四舍五入。

但是,仅在 0.5 边界处四舍五入并不总是足够的。首先是scaling input 1, 1 to sum 3的病态情况:其中一个值必须是2,另一个是1,所以有两个等价的解。

其次,我们可能需要进行不同的舍入:给定 0.1, 0.1, 0.3 和目标 8,我们得到 0.1 / 0.5 * 8 = 1.6 => 20.3 / 0.5 * 8 = 4.8 => 5,总和为 2 + 2 + 5 = 9 而不是 8。

这个例子的好的解决方案是什么?想到这些:

1.6 - 1等我们看到第一个有绝对错误0.6, 0.6, 1.2。我通常想对它们进行平方和求和,所以我们得到:

因此,1, 2, 5(或2, 1, 5)应该是首选。

我实现了一个近似求解器,它考虑剩余 space 剩余(目标总和减去当前总和)来缩放值,这大部分工作正常。我相信这是现有良好解决方案的常见问题,而不是对其进行改进。但是,我找不到它 - 你能指点我吗?

我使用 C/C++/C# 类语言工作,但我只关心这里的通用算法。

考虑下一个简单的方法:

让我们求和S
缩放所有值,并且对于每个缩放的 v 生成一对 Int(v), Frac(v),计算整数部分的总和 - 比如说 ISum,然后增加 S-ISum 对的整数部分与最大的小数零件

您可能会很高兴知道您已接近最佳解决方案。有两个基本步骤:

  1. 确定最近的直接缩放解决方案,高于或低于 所需的目标总和。你的帖子说明你已经掌握了 这部分.

  2. 为了便于说明,我们假设您的目标总和还差 2(整数差)。您现在循环遍历您的解决方案整数 2 次(每个差异单位一次)。您需要找到可以添加 1 最少 增加的元素 "goodness" 指标(幸运的是,它具有所有正确的数学属性使其成为一个可分离的迭代解决方案)。将 1 添加到一个元素,然后转回并再次执行(在某些情况下 可能 是相同的元素,具有广泛的值)。

这是否让您找到解决方案?

这是一个令人惊讶的政治研究问题。也就是如何在不同值数的人群中按比例分配席位的问题。例如,我们 运行 了解如何在各州之间分配国会席位和 multiple methods have been used

每种方法的权衡略有不同。有些人倾向于将更多整数分配给大桶。少一些。在政治背景下,我们通常希望每个人都有一些代表性。

您已选择最小化舍入误差的平方和。为此,我认为只需分配每个低于四舍五入的最小整数就足够了,然后根据您想要的小数部分对它们进行排序,并将剩余的四舍五入分配到顶部。

如果您试图最小化比率差异的平方和,您会得到截然不同的答案。

  1. 计算浮点理想值。
  2. 通过向下舍入为整数创建候选值。
  3. 当候选人总和 < 目标
    • 将错误最大的候选增加1

在python中:

   def convert(weights, target):
       ideals = [v/sum(weights) * target for v in weights]
       candidates = [int(math.floor(t)) for t in ideals]
       while (sum(candidates) < target):
            err = [(c-i)*(c-i) for c,i in zip(candidates, ideals)]
            candidates[err.index(max(err)]+=1
        return candidates