Differential Testing 对拍器的使用

DifferentialTesting是一种通过对比不同实现的程序输出来验证正确性的方法。例如,用一个已知正确或复杂度高的实现与另一个可能有误或效率低的实现进行对比。当两者输出不同时,可能存在错误。文章通过最大子数组问题的例子展示了如何运用该技术进行调试。
摘要由CSDN通过智能技术生成

感谢问求助教 wyy 关于 Differential Testing 的介绍

如何验证程序的正确性?

如果不能通过实时评测来查看程序的正确性,那么该如何验证自己程序的正确性呢?

也许我们会想出几个样例来简单的验证一下。

但是,通过几个样例并不代表整个程序就是正确的。我们要想提高程序的正确性(当然,很难保证其一定完全正确)我们需要更多的样例,并进行调试。调试通过的样例越多,程序正确的可能性也就越大。

时间允许吗?即使时间充足,大部分的问题对应的样本空间几乎均为无穷集。无论如何也很难在有限的时间去调试我们的程序。

Differential Testing

因此,我们需要更加高效的调试代码的工具。Differential Testing 的本质就是所谓的对拍器,通过写两份不同实现的代码来验证程序的正确性。例如:其中一份可能是运用了合适算法的时间复杂度十分优秀的程序,但并不能够确认其正确性。而另一份则是暴力写法Brute - Foece,虽然时间复杂度很高,但是你可能几乎百分百的确认这可以进行正确的输出。此时,你就可以运用 Differential Testing 来迅速的产生数据并将这些数据通过文件流传送到两个程序产生的可执行文件中,并将这两个程序得到的输出再通过文件流输出到另外两个文本中,最后只需要利用程序对这两个文本进行匹配即可。

以最大子数组问题为例

最大子数组问题在我前几次的博客中有提到,并且下述两份具体实现都在那里,大家可以自行查看。

现在手中有两份实现,一份是通过递归实现,时间复杂度在 O ( n 2 ) \mathbb{O}(n^2) O(n2),而另一份实现只有线性复杂度。

事实上,如果两份实现中都不能很确定其正确性,这也是没有关系的。毕竟两种实现的思路不一致,错也不会错得完全一致。正如我们每次做完作业后和同学对一下答案,如果几乎一样,那么正确率也就很高了。

Code :Differential Testing

#include<iostream>
#include<fstream>
using namespace std;

void generate_data()
{
    ofstream fout("input.txt");
    srand(time(0));
    int n = rand() % 50 + 10;
    fout << n << " " << endl;
    for (int i = 1; i <= n; i++)
    {
        int m = rand() % 20 - 5;
        fout << m << " ";
    }
    fout.close();
}

int main()
{
    for (int i = 1; i <= 100; i++)
    {
        cout << "iteration : " << i << endl;
        generate_data();
        system("maxArr1.exe < input.txt > output1.txt");
        system("maxArr2.exe < input.txt > output2.txt");
        if (system("fc output1.txt output2.txt"))
        {
            cout << "Error";
            break;
        }
        //getchar(); 
     }
}
  1. 需要添加头文件 include<fstream>
  2. 函数void generate_data()
    1. 通过rand()函数配合取模操作生成我们期望的合理输入
    2. ofstream fout "input.txt"生成一个input.txt的文本文档来存放我们的输入,通过fout << 进行写入
    3. 关闭文件fout.close()
  3. system("maxArr1.exe < input.txt > output1.txt")即执行 maxArr.exe这个文件,通过input.txt读入数据并生成一个output1.txt文本来写入数据。
  4. system("fc file file")用于匹配两个文本的内容,若不一致则返回1,否则返回0.因此我们可以通过返回值来判断是否有不一致的情况,并终止循环,使得这个错误的样例得以保存下来,便于通过这个样例进行调试来查找程序的错误。

需要注意的是以这种写法给出的,这两个可执行文件应当在同一路径下~

在这里插入图片描述

在短短的三十秒之内我们就在一千份输入样例中的第961份样例中,找到了这两份代码对于同一输入的输出存在不一致。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值