我找到了关于圈复杂度on Wikipedia的以下段落:
可以证明,只有一个入口点和一个出口点的任何结构化程序的圈复杂度等于决策点的数量(即"如果"语句或条件循环)该计划加一。
这意味着两个任意嵌套if语句的圈复杂度为3:
if (a)
{
if (b)
{
foo();
}
else
{
bar();
}
}
else
{
baz();
}
由于将调用这三个函数中的一个,我的内心同意3。
但是,也可以按顺序编写两个任意if语句,而不是嵌套它们:
if (a)
{
foo();
}
else
{
bar();
}
if (b)
{
baz();
}
else
{
qux();
}
现在代码中有四条路径:
这个片段的圈复杂度不应该是4而不是3?
我是否误解了引用的段落?
答案 0 :(得分:11)
循环复杂性定义为代码中线性独立路径的数量。
在你的第二个例子中,我们有以下路径运行...
| # | A | B | Nodes hit |
| 1 | true | true | foo() baz() |
| 2 | true | false | foo() qux() |
| 3 | false | true | bar() baz() |
| 4 | false | false | bar() qux() |
这是完全正确的,这里的执行路径数是4.然而,圈复杂度是3。
关键是要了解圈复杂度的衡量标准:
定义:
线性独立路径是通过程序的任何路径 引入至少一个未包含在任何其他边缘的新边缘 线性独立的路径。
第4条路径与前三条路径不是线性独立的,因为它没有引入任何未包含在前三条路径中的新节点/程序语句。
如the wikipedia article所述,圈复杂度总是小于或等于理论唯一控制流路径的数量,并且总是大于或等于实际可实现的执行路径的最小数量。
(为了验证第二个陈述,想象一下,当输入您描述的代码块时,如果b == a 始终为真)。
答案 1 :(得分:0)
我同意完美主义者的解释。对于Java语言,这是一个更为非正式的解释:
McCabe的循环复杂度(McCC)用于方法表示为其中的独立控制流路径的数量。它表示源代码中可能的执行路径数的下限,同时它是实现完整分支测试覆盖所需的最小测试用例数的上限。度量的值计算为以下指令的数量加1:if,for,foreach,while,do-while,case标签(属于switch指令),catch,条件语句(?:)。此外,逻辑“和”(&&)和逻辑“或”(||)表达式也将值加1,因为它们的短路评估可能导致取决于第一个操作数的分支。不包括以下说明:else,switch,default label(属于switch指令),try,finally。