簡體   English   中英

在這種情況下,為什么“ printf scanf”比“ cout cin”慢?

[英]Why do “printf scanf” is slower than “cout cin” in this case?

我試圖完成UVa問題:11559-活動計划。 但是,我發現一些令我困惑的東西。 我已經使用printf和scanf作為IO編寫了代碼,但是判斷中出現了“超過時間限制”。 然后我使用cin和cout更改了代碼,然后獲得了“接受”。 cin或cout是不是比scanf和printf慢? 這是我的代碼。

“ stdio.h”版本

#define inf 500000000

using namespace std;

int N, B, H, W;
int main ()
{
    while(scanf("%d %d %d %d", &N, &B, &H, &W)){
        int cost = inf;
        for(int i = 0; i < H; i++){
            int P, k ;
            scanf("%d",&P);
            for(int j = 0; j < W; j++){
                scanf("%d",&k);
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) printf("%d\n",cost);
        else{
            printf("stay home\n");
        }
    }
    return 0;

}

“ iostream”版本

#define inf 500000000

using namespace std;

int N, B, H, W;
int main ()
{
    while(!cin.eof()){
        int cost = inf;
        cin >> N >> B >> H >> W;
        if(cin.eof()) break;
        for(int i = 0; i < H; i++){
            int P, k ;
            cin >> P;
            for(int j = 0; j < W; j++){
                cin >> k;
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) cout << cost << endl;
        else{
            cout << "stay home" << endl;
        }
    }
    return 0;
}

不, cincout與使用printf / scanf並無顯着差異。 但是, endl將調用ofstream::flush() ,它與printf("%d\\n", cost); fflush(stdout); printf("%d\\n", cost); fflush(stdout); ,並且我希望您這樣做的話,它在那里的運行速度也會變慢。

同樣,將cinscanf或類似的東西混合會增加更多的時間,因為代碼必須始終“同步”兩個I / O流。 我建議您將scanf輸入重寫為:

while(scanf("%d %d %d %d", &N, &B, &H, &W) != EOF){
    int cost = inf;
    // remove scanf and cin.eof() line here
    ...
}

為了證明我的觀點(至少是輸出):

#include <iostream>
#include <cstdio>

using namespace std;

static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

int main(int argc, char **argv)
{

    unsigned long long t = rdtsc();
    if (argc > 1)
    {
        for(int i = 0; i < 1000; i++)
        {
            printf("%d", i);
        }
    }
    else
    {
        for(int i = 0; i < 1000; i++)
        {
            cout << i << "\n";
        }

    }

    t = rdtsc() - t; 
    cerr << "Time: " << t << endl;
}

當不帶參數( argc == 1 )運行並帶參數( argc == 2 )運行時,此輸出為:

$ ./a.out > foo.txt
Time: 1672894
$ ./a.out 1 > foo.txt
Time: 1513620

支持printf大約相差10%。 但是,當我運行任何基准測試時,我的系統中會有相當大的差異,因此應注意一點。 注意,使用endl代替"/n"會有很大的不同!

對於cin主場迎戰scanf ,有一個的缺點多一點差別scanf

#include <iostream>
#include <cstdio>

using namespace std;

static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

int main(int argc, char **argv)
{

    unsigned long long t = rdtsc();
    if (argc > 1)
    {
        for(int i = 0; i < 1000; i++)
        {
            int tmp;
            scanf("%d", &tmp);
        }
    }
    else
    {
        for(int i = 0; i < 1000; i++)
        {
            int tmp;
            cin >> tmp;
        }

    }

    t = rdtsc() - t; 
    cerr << "Time: " << t << endl;
}


$ ./a.out < foo.txt
Time: 1990454
$ ./a.out 1 < foo.txt
Time: 4804226

如您所見, scanf慢了將近2.5倍...但是,我也看到了其他情況,它們之間的差別並不大。 我不完全確定為什么這里有這么大的差異。

總而言之,兩者之間存在差異,但是我相信James Kanze的答案更接近於解釋正在發生的事情-代碼根本無法完成,因為cin.eof()不會由scanf設置。

可以肯定的是: scanfstd::cin.eof()沒有影響。 因此,您的第一個代碼有一個無限循環。 第二個代碼實際上從std::cin讀取內容,並最終使std::cin.eof()返回true。

但是,這兩個代碼都有許多其他問題。 給定您的水平,您應該忘記scanf 這遠非危險而復雜。 到處使用std::cin 並檢查其是否成功輸入 ,但使用效果(總是)前。 std::cin.eof() 告訴你前面的輸入是否成功,也不確定下一個會成功或失敗。直到你知道,以前的輸入失敗,它的使用可能是一個錯誤。)

編寫代碼的慣用方式將涉及以下內容:

while ( std::cin >> N >> B >> H >> W ) ...

(除非沒有經驗豐富的C ++程序員會為它們使用全局變量;因此,也不要使用單個大寫字母作為名稱。)其他輸入也應以類似方式處理。

好。 我知道答案已經存在,但是我仍然看不到OP為何會觀察到的明確解釋。 因此,要從James's和Mats's的答案中獲得最大的收益,我將嘗試獲得一個很好的易於理解的解釋。

事情是第一次代碼不能運行每本身慢。 就像詹姆斯所說的那樣,有一個可能的無限循環。

為什么第一段代碼運行速度較慢? 由於無休止的循環,自動判斷會在時間限制后將其殺死。 算法和I / O並不慢。

給定您的時間差:0.022s至1s。 (實際上)由於c和c ++之間的I / O實現差異,不可能有如此大的差異。

我沒有輸入示例。 但是我的賭注是,如果您從Mats的答案中獲得建議,並使用以下代碼,則第一個代碼將正常工作並給出相同的時間結果。

#include <stdio.h>
#include <stdlib.h>
#define inf 500000000
int N, B, H, W;
int main ()
{
    while(scanf("%d %d %d %d", &N, &B, &H, &W) != EOF){ //Mats' suggestion
        int cost = inf;
        //if(cin.eof()) break; //not needed `while` checks it
        for(int i = 0; i < H; i++){
            int P, k ;
            scanf("%d",&P);
            for(int j = 0; j < W; j++){
                scanf("%d",&k);
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) printf("%d",cost);
        else{
            printf("stay home\n");
        }
    }
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM