我有两个java源代码文件做同样的事情,给出相同的输出。它们包含的代码略有不同,如下例所示。我需要一种算法来消除这两个java代码文件之间的相似度(相同性)。
示例
/* First file */
public int inc (int n) {
return ++n;
}
/* Second file */
public int inc (int n) {
return (n+1);
}
是否有算法显示这两个文件做同样的事情?
提前致谢
答案 0 :(得分:4)
正如阿兰图灵近一个世纪前所证明的那样,没有一般的算法可以确定函数的评估是否会在有限的时间内完成(参见 Halting problem )。
暗示没有通用算法可以决定两段代码是否具有相同的输出。另一方面,如果你假设函数总是在有限的时间内完成,那么一个简单的算法可以完成你想要的只是运行所有可能输入的代码。
答案 1 :(得分:1)
忽略所有复杂的细节,这是一个天真的学校级算法来做到这一点。
测试1 :首先计算两个程序中使用的变量数量。查看它们之间的差异,并根据您的需要和您要比较的程序确定通过测试的阈值差异。 / p>
测试2 :然后确定在两个程序中使用最多次数的变量的数据类型,如果数据类型不同,那么在大多数情况下程序会有所不同,但并不总是情况下。
测试3 :您可以比较圈复杂度。这也有助于确定相似度,因为它会告诉您程序中独立路径的数量。
可以有更多的测试,例如比较块数或函数调用,你可以将相似率设置为等于传递的测试百分比。
但当然这个算法是天真的,并且会有失败的测试用例,但对于基础知识和开始,我认为它应该没问题。
答案 2 :(得分:0)
遗憾的是,没有这样的算法。
为什么呢?请参阅:https://www.cs.rochester.edu/~nelson/courses/csc_173/computability/undecidable.html
特别是标有“等价问题是不可判定的”的部分
要真正理解为什么有助于熟悉可判定性,图灵机和各种其他类型的自动机等领域
答案 3 :(得分:0)
如果您期待编写一个可以检测类似工作的程序,可以尝试搜索软件Turnitin
的工作原理。
虽然不可能提出适用于所有情况的算法。您可以采用一些解决方案。
您可以为某些字词/代码创建“同义词”。示例x++
类似于x+=1
,x=x+1
,++x
等。但请注意,有时x++
和++x
在编码时意味着完全不同的东西。所以你的程序永远不能100%准确地判断相似性。
您的“同义词”数据库必须足够大才能处理各种情况。
但是,请注意,人们总是可以通过模糊代码或对其添加混淆来绕过检测。
示例:代替编写x++
,他们可以编写x=(x+2)-1
,这意味着同样的事情,无论您的同义词数据库有多大,您都无法捕捉到
如果你的程序不仅要检查代码,还要检查论文和期刊。您可以对书写模式进行文本分析。 (例如,使用字长频率计数)。有些作者可能更喜欢使用较短的单词,而有些则喜欢较长的单词。
您可以使用许多其他分析来使您的程序成为动态程序。即使没有这样的算法,但绝对有可能编写这样的程序来检测抄袭。