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
和 <= 1
和 int
所以我们只有 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
先决条件:
- 硬币或钞票必须按降序排列
我的最终结果:
好的,找出最适合我的解决方案:
首先,我发现一些 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 个数字的列表,那么组合太多。
我在电子表格上有一个数字,它是列表中许多不同数字的组合。
例如:
列表包含: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
和 <= 1
和 int
所以我们只有 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
先决条件:
- 硬币或钞票必须按降序排列
我的最终结果:
好的,找出最适合我的解决方案:
首先,我发现一些 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 个数字的列表,那么组合太多。