C++ 在流中搜索丢失的数字时表现不直观

C++ 在流中搜索丢失的数字时表现不直观,c++,arrays,performance,C++,Arrays,Performance,概述: 学习C++ 练习 了解(Java)和(C),但答案不足以回答我的问题 挑战: 按从1到N的随机顺序馈送整数 缺少一个-打印它 T是测试用例的数量 N>numTests; 而(numTests--) { 无符号透镜计数; cin>>透镜计数; 无符号lenCount数组(lenCount); 而(--lenCount) { 无符号输入; cin>>输入; 输入[输入-1]=1; } for(无符号索引=0;索引!=lenArray;++index) { 如果(输入[索引]==0) {

概述:

  • 学习C++
  • 练习
  • 了解(Java)和(C),但答案不足以回答我的问题
挑战:

  • 按从1到N的随机顺序馈送整数
  • 缺少一个-打印它
  • T是测试用例的数量
  • N>numTests; 而(numTests--) { 无符号透镜计数; cin>>透镜计数; 无符号lenCount数组(lenCount); 而(--lenCount) { 无符号输入; cin>>输入; 输入[输入-1]=1; } for(无符号索引=0;索引!=lenArray;++index) { 如果(输入[索引]==0) { 无法测试; 而(numTests--) { 无符号列阵; cin>>透镜阵列; 无符号答案=(lenArray*(lenArray+1))/2; 而(--lenArray) { 无符号输入; cin>>输入; 答案-=输入; }
    cout在进入我的结果之前,您的第一个程序中有一个错误:您缺少
    输入。在声明
    输入后立即填充(0);
    ——数组的内容默认初始化,这意味着不执行初始化,因为
    unsigned
    不是类类型


    我用我编写的(固定的)第一个程序、第二个程序和第三个程序对10000个测试进行了测试,每个测试有1000个数字。我发现所有三个程序在误差范围内持续运行大约两秒钟。也就是说,它们对这组特定输入的性能相当

    所有样本均使用
    g++-std=c++11-O3-Wall-pedantic
    进行编译。
    g++--version
    的输出:
    g++(Debian 4.9.2-10)4.9.2

    第三个项目是:

    #include <iostream>
    
    int main() {
        unsigned t;
        while (std::cin >> t);
        return 0;
    }
    
    #包括
    int main(){
    无符号t;
    while(std::cin>>t);
    返回0;
    }
    
    惊讶

    这里的教训是格式化的I/O非常慢,非常慢

    尽管从理论上讲,阵列算法的速度至少是基于数学的算法的三倍(每次试验的平均循环迭代次数为2500次,而不是基于数学的算法的1000次),格式化I/O的开销如此之高,以至于两种算法对于如此小的数字列表的效率差异通过比较是微不足道的

    这就像有三个几乎装满水的浴缸(每个浴缸的水量相同)然后在其中一个桶中加入三滴,在第二个桶中加入一滴,在第三个桶中不加入任何东西,然后想知道为什么水位仍然基本相同。初始注水表示格式化I/O的开销,添加的水滴表示实际算法运行的时间

    旁白:这就是我们告诉人们不要过早优化的原因。事实上,你通常认为瓶颈比实际瓶颈几乎总是要快很多数量级:等待某种I/O(通常是磁盘或网络).这并不是说你不应该优化,但通常你应该在基准测试后进行优化,因为热门路径很少是你认为会出现的


    (我无法解释为什么基于阵列的算法在您的测试中会显著更快;我的测试根本没有证明这一点。在无法访问测试机器、基准方法或任何差异解释的情况下,我倾向于将这些结果视为有缺陷。)

    数组方法在给定此错误(应该是lencount)的情况下是否实际工作?对于(unsigned index=0;index!=lenArray;++index)@DaveS,它不应该是
    lencount
    ,因为
    lencount
    在该点为零。您如何测量它们的运行时间,以及使用什么输入?>“@DaveS它不应该是lencount,因为lencount在那个点上是零”你是对的,但是lenArray是数组本身,所以lenArray.size()然后。@DaveS不,整个数组可能不会被填充。
    cin>>lenCount;
    设置实际使用的数组元素数,然后用这个值填充
    lenArray
    。这就像有一个容量为1000但大小为50的向量。例如。哇。为什么它这么慢?IO通常很慢(涉及到系统和上下文切换),C++ IoSoW增加了大量开销,特别是对于格式化输入。
    #include <iostream>
    using std::cin;
    using std::cout;
    using std::endl;
    
    int main()
    {
        unsigned numTests;
        cin >> numTests;
        while (numTests--)
        {
            unsigned lenArray;
            cin >> lenArray;
            unsigned answer = (lenArray*(lenArray+1))/2;
            while (--lenArray)
            {
                unsigned input;
                cin >> input;
                answer -= input;
            }
    
            cout << answer << endl;
        }
    
        return 0;
    }
    
    #include <iostream>
    
    int main() {
        unsigned t;
        while (std::cin >> t);
        return 0;
    }