7

これは、他のいくつかの質問での議論から派生したものです。

非常に長い文字列を大量に解析する必要があるとします。各文字列には、double空白で区切られた一連のs(もちろんテキスト表現)が含まれています。を解析doubleして。にする必要がありList<double>ます。

標準の解析手法(string.Split+を使用double.TryParse)は非常に遅いようです。数値ごとに文字列を割り当てる必要があります。

私はそれを古いCのような方法にしようとしました:数字を含む部分文字列の最初と最後のインデックスを計算し、追加の文字列を作成せずに「その場で」解析します。(以下の関連部分を示すhttp://ideone.com/Op6h0を参照してください。)

int startIdx, endIdx = 0;
while(true)
{
    startIdx = endIdx;
    // no find_first_not_of in C#
    while (startIdx < s.Length && s[startIdx] == ' ') startIdx++;
    if (startIdx == s.Length) break;
    endIdx = s.IndexOf(' ', startIdx);
    if (endIdx == -1) endIdx = s.Length;
    // how to extract a double here?
}

のオーバーロードがありstring.IndexOf、指定された部分文字列内でのみ検索しますが、実際にその部分文字列を最初に抽出せずに、部分文字列からdoubleを解析する方法を見つけることができませんでした。

誰かアイデアがありますか?

4

2 に答える 2

7

サブストリングからdoubleを解析するためのマネージAPIはありません。私の推測では、double.Parseでのすべての浮動小数点演算と比較して、文字列の割り当ては重要ではありません。

とにかく、空白のみで構成される長さ100の「バッファ」文字列を1回作成することで、割り当てを節約できます。次に、解析する文字列ごとに、安全でないコードを使用して文字をこのバッファ文字列にコピーします。バッファ文字列を空白で埋めます。また、解析にはNumberStyles.AllowTrailingWhiteを使用できます。これにより、末尾の空白が無視されます。

文字列へのポインタの取得は、実際には完全にサポートされている操作です。

    string l_pos = new string(' ', 100); //don't write to a shared string!
    unsafe 
    {
        fixed (char* l_pSrc = l_pos)
        {               
              // do some work
        }
    }

C#には、文字列をchar*にバインドするための特別な構文があります。

于 2012-04-15T11:54:59.763 に答える
2

あなたがそれを本当に速くやりたいのなら、私はステートマシンを使うでしょう

これは次のようになります。

enum State
{
    Separator, Sign, Mantisse etc.
}
State CurrentState = State.Separator;
int Prefix, Exponent, Mantisse;
foreach(var ch in InputString)
{
    switch(CurrentState)
    { // set new currentstate in dependence of ch and CurrentState
        case Separator:
           GotNewDouble(Prefix, Exponent, Mantisse); 


    }

}
于 2012-04-15T13:12:08.410 に答える