Excel VBA实现n个k面骰子指定和计数函数调用报#VALUE错误
问题描述
- 需求:计算投掷n次k面(点数范围为1至k)骰子时,得到指定总和sum的所有可能情形的数量
- 异常现象:编写对应VBA自定义函数后,在Excel工作表中调用时,无论传入什么输入参数都返回
#VALUE错误;同模块下其他自定义函数在同一张工作表中可正常运行 - 原函数代码:
Function how_many_ways(n, k, sum) If n = 0 Then If sum = 0 Then how_many_ways = 1 Else how_many_ways = 0 End If End If If sum < 0 Or k * n < sum Or n > sum Then how_many_ways = 0 End If res = 0 For i = 1 To k res = res + how_many_ways(n - 1, k, sum - i) Next i how_many_ways = res End Function
故障原因
- 核心问题为递归逻辑缺少终止机制:两个边界判断分支完成赋值后,未终止函数执行,会继续向下运行后续的递归循环,触发无限递归导致栈溢出,最终返回
#VALUE错误- 当
n=0的分支判断完成赋值后,代码依然会继续执行后续的边界校验、变量初始化和递归调用 - 当目标和越界的分支判断完成赋值后,同样不会停止执行,仍会运行后续的递归循环
- 当
- 次要问题:参数名
sum与VBA内置函数Sum重名,可能引发隐式冲突;所有变量未显式声明,代码健壮性不足
修正方案
- 给两个边界判断分支增加
Exit Function语句,触发边界条件时直接返回结果,不再执行后续逻辑 - 为所有参数、变量添加显式类型声明,参数名更换为与内置函数不冲突的名称
修正后可正常运行的代码:
Function DiceCombination(n As Long, k As Long, target_sum As Long) As Long ' 边界条件1:投掷次数为0时,仅当目标和为0时返回1种合法情况 If n = 0 Then If target_sum = 0 Then DiceCombination = 1 Else DiceCombination = 0 End If Exit Function End If ' 边界条件2:目标和超出合法范围时直接返回0 If target_sum < 0 Or k * n < target_sum Or n > target_sum Then DiceCombination = 0 Exit Function End If Dim res As Long res = 0 Dim i As Long ' 遍历单轮骰子的所有可能点数,累加剩余投掷轮次的合法组合数 For i = 1 To k res = res + DiceCombination(n - 1, k, target_sum - i) Next i DiceCombination = res End Function
调用示例
在工作表中直接输入公式即可,例如计算投掷3次6面骰子、总和为10的合法情形数,输入:=DiceCombination(3,6,10)
即可返回结果27。
内容的提问来源于stack exchange,提问作者Kyjko
相关产品推荐
相关产品推荐

