【发布时间】:2012-09-26 10:43:48
【问题描述】:
我想知道两段代码的圈复杂度,
IF((A>B) AND (C>D))
{ a=a+b;c=c+d;}
据我所知,上述代码的圈复杂度=2+1=3,
另一个代码
IF((A>B) OR (C>D))
{a=a+b;c=c+d;}
以上代码的复杂度是=4+1=5,
上述复杂性是否正确?
【问题讨论】:
我想知道两段代码的圈复杂度,
IF((A>B) AND (C>D))
{ a=a+b;c=c+d;}
据我所知,上述代码的圈复杂度=2+1=3,
另一个代码
IF((A>B) OR (C>D))
{a=a+b;c=c+d;}
以上代码的复杂度是=4+1=5,
上述复杂性是否正确?
【问题讨论】:
两个复杂度相同且等于 3,以 4 种方式计算。我同意 Neil 使用 De Morgan 证明它们是相同的,我认为可以从对复杂性计数很重要的图表中看到相同的情况。
让我们从两个代码段的图表开始。
解释的话:
if and if 和 if or if,所以有两个 if。因此我的第二个节点是一个单独的节点。 如您所见,两个代码段之间的数字没有区别。节点、边、区域都是一样的。区别在于哪个节点与哪个节点连接,这来自于短路的工作原理。显然,对于没有它的语言,图表需要有所不同。
不止一个。复杂度等于
边数 = 5;节点 = 4;退出 = 1;
两种情况下的复杂度 = 5-4+2*(1) = 3。此定义不需要强连通图,因此我们删除了添加的边。
边数 = 6;节点 = 4;退出 = 1;
两种情况下的复杂度 = 6-4+1 = 3。这个定义的出现是因为它在拓扑上更有意义,并且在循环计数(图形方式)方面更容易考虑。当您考虑计算许多例程/函数的复杂性时,它会更有用,比如类中的所有方法。因此,认为可以在循环中调用函数是有道理的。但我离题了。
地区:3。
这来自欧拉公式 区域 + 节点 - 边 = 2 改写这个: 区域 = 边 - 节点 + 2
因此,区域的数量与复杂性相同(假设一个出口点)。这是为了在单出口子例程中简化图表中的计数复杂性。
McCabe 自己指出
在实践中,复合谓词如 IF "c1 AND c2" THEN 被视为有贡献 两个复杂度,因为没有连接词 AND 我们将有 IF c1 THEN IF c2 THEN 它有两个谓词。出于这个原因和测试目的,已经发现 在计算复杂度时更方便计算条件而不是谓词
在两个代码段中,我们都有一个复合条件,所以 Decisions = 2;
复杂度 = 2+1 = 3。
值得注意的是,圈复杂度以计数循环开始,但出于实用目的以计数条件结束。
先试试 McCabe 的论文:http://www.literateprogramming.com/mccabe.pdf
维基百科有一篇很好的文章依赖于该论文,但我发现如果不遵循基本块和连接组件是不够的:
我在钱伯斯的页面上找到了一个简洁但很好的总结:http://www.chambers.com.au/glossary/mc_cabe_cyclomatic_complexity.php
第 8 章中的“软件工程集成方法”一书有一个示例说明复杂性计算(尽管我认为他们在图上吃了一条边,图 8.7)。
http://books.google.pl/books?id=M-mhFtxaaskC&lpg=PA385&ots=jB8P0avJU7&d&hl=pl&pg=PR1#v=onepage
【讨论】:
我认为它们具有相同的圈复杂度 3;这可以使用德摩根定律来证明。
IF((A>B) OR (C>D)) {a=a+b;c=c+d;} ELSE {}
IF(!((A>B) OR (C>D))) {} ELSE {a=a+b;c=c+d;}
IF(!(A>B) AND !(C>D)) {} ELSE {a=a+b;c=c+d;}
查看它的另一种方法是获取图形并交换条件块和退出点(并反转它们之间的边),这会将其从 AND 转换为 OR,而不会更改节点或边的数量。
【讨论】: