7

を使用して正の整数の大規模な解析を行っていscanf("%d", &someint)ました。scanf がボトルネックかどうかを確認したかったので、次のように を使用して単純な整数解析関数を実装しましたfread

int result;
char c;

while (fread(&c, sizeof c, 1, stdin), c == ' ' || c == '\n')
    ;

result = c - '0';
while (fread(&c, sizeof c, 1, stdin), c >= '0' || c <= '9') {
     result *= 10;
     result += c - '0';
}

return result;

しかし、驚いたことに、この関数のパフォーマンスは (インライン化されていても) 約 50% 悪化しています。特殊なケースで scanf を改善する可能性はありませんか? 高速ではないfreadはずです(追加のヒント:整数は(編集:ほとんど)1桁または2桁です)?

4

4 に答える 4

4

バッファリングすることで、例を大幅に改善できます。メモリに多数の文字を読み込み、メモリ内のバージョンからそれらを解析します。

ディスクから読み取る場合は、バッファがブロックサイズの倍数になるため、パフォーマンスが向上する可能性があります。

編集: mmapを使用してファイルをメモリにマップすることにより、カーネルにこれを処理させることができます。

于 2011-12-12T23:51:48.650 に答える
1

ここに私が使用するものがあります。

 #define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
 char _;

ただし、これは整数でのみ機能します。

于 2015-01-17T01:45:37.987 に答える
-2

あなたの言うことから、私は次の事実を導き出します。

  • 数値は 0 ~ 99 の範囲で、10+100 個の異なる文字列 (先頭のゼロを含む) を占めます。
  • 入力ストリームが何らかの仕様に準拠しており、予期しない文字シーケンスが含まれていないことを信頼している

その場合、ルックアップ テーブルを使用して文字列を数値に変換します。文字列 s[2] を指定すると、ルックアップ テーブルのインデックスは、数字を交換し、ASCIIで等しいs[1]*10 + s[0]という事実を利用して計算できます。'\0'0

次に、次の方法で入力を読み取ることができます。

// given our lookup method, this table may need padding entries
int lookup_table[] = { /*...*/ };

// no need to call superfluous functions
#define str2int(x) (lookup_table[(x)[1]*10 + (x)[0]])

while(read_token_from_stream(stdin, buf))
        next_int = str2int(buf);

今日のマシンでは、より高速な技術を思いつくのは難しいでしょう。私の推測では、このメソッドは、scanf()ベースのアプローチよりも 2 倍から 10 倍高速に実行される可能性があります。

于 2011-12-13T00:37:15.813 に答える