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

时间:2019-03-26 17:13:05

标签: algorithm numeric

我想将浮点数数组转换为整数数组。整数应加起来为一个给定的值,并且它们的值应与缩放后的输入数组相似。

换句话说,完美结果由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边界处取整并不总是足够的。首先,在病理情况下,将输入1, 1缩放为总和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, 1, 6
  • 1, 2, 5
  • 2, 2, 4

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

  • 1, 1, 6-> (1.6 - 1)^2 + (1.6 - 1)^2 + (4.8 - 6)^2 = 0.36 + 0.36 + 1.44 = 2.16
  • 1, 2, 5-> (1.6 - 1)^2 + (1.6 - 2)^2 + (4.8 - 5)^2 = 0.36 + 0.16 + 0.04 = 0.56
  • 2, 2, 4-> (1.6 - 2)^2 + (1.6 - 2)^2 + (4.8 - 4)^2 = 0.16 + 0.16 + 0.64 = 0.96

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

我实现了一个近似求解器,该函数考虑剩余的空间(目标总和减去当前总和)来缩放值,大多数情况下都可以。我认为,除了改进它之外,我认为这是现有良好解决方案的普遍问题。但是,我找不到它-您能指出我吗?

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

4 个答案:

答案 0 :(得分:1)

考虑下一个简单的方法:

让我们求和S
缩放所有值,并为每个缩放的v制作一对Int(v), Frac(v),计算整数部分的总和-例如ISum,然后以最大的分数递增S-ISum对的整数部分零件

答案 1 :(得分:1)

您可能很高兴知道自己正处于最佳解决方案的门口。有两个基本步骤:

  1. 确定最接近的直接缩放比例解决方案,无论是上方还是下方 所需的目标金额。您的帖子显示您已掌握 这部分。

  2. 出于说明的目的,我们假设您仍比目标总和少2(整数差)。现在,您将遍历您的解决方案整数2次(每单位差一个)。您需要找到可以在您的“善意”指标中增加最少的元素添加1的元素(幸运的是,该元素具有所有正确的数学属性,可将其分离,迭代解决方案)。将1添加到一个元素,然后向后旋转并再次执行(在某些情况下, 可以是相同的元素,并且值范围很广)。

这会让您找到解决方案吗?

答案 2 :(得分:1)

这是一个在政治上研究得令人惊讶的问题。确切的问题是如何在具有不同价值数的人群之间按比例分配席位。例如,我们遇到了如何在各州和multiple methods have been used之间分配国会席位的问题。

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

您已选择最小化四舍五入误差的平方和。为此,我认为只需为舍入以下的每个最小整数赋值,然后根据您想要的更多小数的顺序对其进行排序,然后将剩余的舍入分配到顶部。

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

答案 3 :(得分:1)

  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