Excel 查找数字组合的函数

Excel Function to find a combination of numbers

我在电子表格上有一个数字,它是列表中许多不同数字的组合。

例如:

列表包含:100、200、250、500 和 1000
我需要说明的数字是:800

答案是 500、200、100。

我正在处理超过 1500 个货币单元格($xxxx.xx),总数为(但并非所有都被使用,所以 SUM 没用).我需要了解哪些数字用于计算总数(这不是公式,它是一个硬编码数字)。

问题:
是否有函数或 VBA 会系统地组合给定范围内的数字,直到它确定可以将哪些数字加在一起得出总数?

我想在开始编写暴力算法之前知道。

你可以在excel中使用SOLVER得到结果。

您可以在 ADD-INS 中激活它,它应该会显示在 DATA 选项卡中。

您这样设置电子表格:

在一栏中您有要检查的数字列表 下一列全为零 (0) 第三列是 First*Second(例如 100 * 0)所以在开始时所有行都为零

比您添加第三列的摘要,它也应该为零。此数据的示例:

100 0   0
200 0   0
500 0   0
50  0   0
60  0   0
80  0   0
120 0   0
90  0   0
TOTAL   0

现在您 运行 solver 形成 data 选项卡,您将获得必须提供参数的界面:

目标值是CELL与所有乘法的总和 您正在查找确切的值(输入 800)

通过更改 cels:select 第二列中的零范围

添加三个附加限制(add 按钮): 零的范围必须是 >= than 0<= 1int 所以我们只有 0 和 1 作为可能的结果 (每次添加限制都必须重新select范围)

现在按 solve 一段时间后(取决于您的数据集的规模,范围从几秒到几分钟不等),它会将一些零更改为 1,指示哪些数字用于生成您的结果。

如果有很多可能的结果,它会选择他找到的一个,但不会指明还有更多,但 运行再次选择它可能会产生不同的结果。

这是我得到的结果:

100 1   100
200 0   0
500 1   500
50  0   0
60  0   0
80  1   80
120 1   120
90  0   0
TOTAL   800

帮助正在路上。

您可以将此函数粘贴到模块中并根据需要进行调整。

Function GetCombination(CoinsRange As Range, SumCellId As Range) As String
Dim Nb As Integer
Dim Com As String
Dim Sum As Double
Dim r As Range
Set r = CoinsRange
Sum = SumCellId.Value
For Each cell In r.Cells
If Sum / cell.Value >= 1 Then
Com = Com & Int(Sum / cell.Value) & " of " & cell.Value & "  "
Sum = Sum - (Int(Sum / cell.Value)) * cell.Value
End If
Next
GetCombination = Com
End Function

先决条件:

  1. 硬币或钞票必须按降序排列

我的最终结果:

好的,找出最适合我的解决方案:

首先,我发现一些 vba 可以让你创建无限的二进制字符串(而不是 Excel 内置的 9 位)。然后我使用这段代码为此目的创建了一个 UDF...因为我正在处理 20-40 "bits" 的块,所以这是绝对必要的。

其次,我做了一个加1的计数器循环,然后改变了二进制字符串来反映新的数字。 (1,10,11,100,101,110,111 等)

第三,我写了一个公式,将二进制字符串打散,把每一个1或0赋值给旁边单元格中对应的数字。 (只需使用 LEN()RIGHT()MID() 函数来识别 1 和 0)。

第四,我把每个值都乘以旁边的1或者0,然后把所有相乘的数的和和我要找的目标值进行比较

100% 的时间,如果给出干净的数据,这会找到一个解决方案(如果存在的话)。 (虽然大多数时间是一个因素,因为这是一个指数函数,所以你拥有的位数越多,循环它们所需的时间就越长)

这个 运行 在 4 分钟内有大约 300 万种组合,取舍取决于几个因素

我重做了工作表,并通过 5 列,每列递增 1,并使计数器递增 5(而不是 1),使速度提高了一倍。

我一直在开发 windows 应用程序来执行此操作。我即将找到一个我认为可以满足大多数人需求的解决方案。

组合的数量是大多数算法的问题,所以关键是尽可能多地忽略不可行的组合。

一个列表中的 25 个数字大约有 3300 万种组合。 列表中的 50 个数字是一百万种组合。 所以,在 vba 中这样做对大多数人来说可能不是一个可行的选择,求解器也不会很好地处理这个问题。

暴力破解是行不通的,因为如果您正在做一个超过 2 到 3 个数字的列表,那么组合太多。