1

高速 I/O 用にこのコードを見つけました。

    #include <cstdio>

inline void fastRead_int(int &x) {
    register int c = getchar_unlocked();
    x = 0;
    int neg = 0;

    for(; ((c<48 || c>57) && c != '-'); c = getchar_unlocked());

    if(c=='-') {
        neg = 1;
        c = getchar_unlocked();
    }

    for(; c>47 && c<58 ; c = getchar_unlocked()) {
        x = (x<<1) + (x<<3) + c - 48;
    }

    if(neg)
        x = -x;
}

inline void fastRead_string(char *str)
{
    register char c = 0;
    register int i = 0;

    while (c < 33)
        c = getchar_unlocked();

    while (c != '\n') {
        str[i] = c;
        c = getchar_unlocked();
        i = i + 1;
    }

    str[i] = '\0';
}

int main()
{

  int n;
  char s[100];

  fastRead_int(n);
    printf("%d\n", n);

  fastRead_string(s);
    printf("%s\n", s);
  return 0;
}

ビットごとのシフト (x<<1) + (x<<3) があるのはなぜですか? また、マイナスと数字以外の文字を入力するとどうなりますか?

4

3 に答える 3

8

ビットごとのシフト (x<<1) + (x<<3) があるのはなぜですか?

ビット単位の左シフトnは、 を乗算することと同じ2^nです。したがって、この式は 10 倍するのと同じです ( から2^1 + 2^3 = 2 + 8 = 10)。

このコードは、(a) シフトと加算は乗算よりもはるかに高速であり、(b) コンパイラは 10 を乗算する最善の方法を認識していないという信念に基づいて、このように記述されています。これらの仮定は両方とも、ほとんどの最新のプラットフォームでは間違っています。

x = x*10 + c - '0';    // '0' is more readable, and portable, than 48.

読みやすくなるだけでなく、より高速になる可能性があります。

また、マイナスと数字以外の文字を入力するとどうなりますか?

最初のループは「-」と数字以外をスキップします。2番目は、数字以外が検出されると停止します(ストリームからその文字を消費した後)。そのため、入力ストリームで見つかった最初の 10 進整数を返します。何もない場合はゼロを返します。たとえば、入力が

xxxx123-456xxx-1234xxx

123最初の呼び出しは、2 番目456(-が最初の呼び出しによって消費されたため)、3 番目-1234、およびそれ以降の呼び出しは を返します0

于 2013-08-05T15:09:20.613 に答える
5

これは本当に悪いコードです。'0'手始めに、なぜand 'ではなく 48 と 57 なのか9'。そして、あなたの質問に関しては、ビット単位のシフトは難読化に使用され、おそらく物事を遅くするために使用されます。式(x << 1) + (x << 3)は と同じ数学値を持ちます10 * x。可読性が大幅に低下し、一部のコンパイラの最適化に干渉する可能性があります。(2 つのシフトと加算が乗算よりも高速なプロセッサでは、コンパイラは、シフトしている理由を知っているため、通常、書き出すよりも優れた変換を行います。) そして、2 番目の質問については、次のとおりです。問題のコードは、数字またはマイナス記号が見つかるまで、すべての文字を無視してスキップします。わずかなエラーもなく、 のよう"abc12"なものに変換 されます。12

実際、エラーチェックがまったくない (およびgetchar_unlockedではなく を使用getcharしている) ため、高速になります。

于 2013-08-05T15:09:19.317 に答える