0

私のコードでは、整数の文字列表現を値に変換する必要がlongありdoubleます。

文字列表現はバイト配列 ( byte[]) です。たとえば、数値12345文字列表現は{ 49, 50, 51, 52, 53 }

現在、 への変換には次の明らかなコードを使用しますlong(および への変換にはほぼ同じコードを使用しますdouble) 。

private long bytesToIntValue()
{
    string s = System.Text.Encoding.GetEncoding("Latin1").GetString(bytes);
    return long.Parse(s, CultureInfo.InvariantCulture);
}

このコードは期待どおりに機能しますが、私の場合はもっと良いものが必要です。現在、最初にバイトを文字列に変換する必要があるためです。

私の場合、bytesToIntValue()約 1200 万回呼び出され、すべてのメモリ割り当ての約 25% がこのメソッドで行われます。

確かに、私はこの部分を最適化したいです。中間文字列なしで変換を実行したい (+ 速度、- 割り当て)。

あなたは何をお勧めします?中間文字列なしで変換を実行するにはどうすればよいですか? 変換を実行するためのより高速な方法はありますか?

編集:

私が扱っているバイト配列には、常に ASCII エンコードされたデータが含まれています。数値は負になる場合があります。double 値の場合、指数形式が許可されます。16 進整数は使用できません。

4

3 に答える 3

3

中間文字列なしで変換を実行するにはどうすればよいですか?

それぞれbyteをに簡単に変換できますchar。例 - 未テスト:

private static long ConvertAsciiBytesToInt32(byte[] bytes)
{
    long value = 0;
    foreach (byte b in bytes)
    {
        value *= 10L;
        char c = b; // Implicit conversion; effectively ISO-8859-1
        if (c < '0' || c > '9')
        {
            throw new ArgumentException("Bytes contains non-digit: " + c);
        }
        value += (c - '0');
    }
    return value;
}

これは実際にはASCII(または互換性がある)であると想定していることに注意してください.バイト配列が実際にUTF-16である場合(たとえば)、間違いなく間違ったことをします.

また、これは長さの検証やオーバーフローのチェックを一切実行しないことに注意してください...そして負の数には対応していません。必要に応じてこれらすべてを追加することもできますが、要件を十分に把握していないため、複雑さを追加する価値があるかどうかを判断できません。

于 2013-01-19T09:50:35.523 に答える
1

それを行う簡単な方法があるかどうかはわかりません. 他のエンコーディングでは動作しないことに注意してください. 私のコンピュータでのテストでは, これは 3 倍しか速くないことが示されました (私はそれが価値があるとは思いません) .

コード + テスト:

class MainClass
{
    public static void Main(string[] args)
    {
        string str = "12341234";
        byte[] buffer = Encoding.ASCII.GetBytes(str);

        Stopwatch sw = Stopwatch.StartNew();
        for(int i = 0; i <   1000000 ;i ++)
        {
            long val = BufferToLong.GetValue(buffer);
        }
        Console.WriteLine (sw.ElapsedMilliseconds);
        sw.Restart();
        for (int i = 0 ; i < 1000000 ; i++)
        {
            string valStr = Encoding.ASCII.GetString(buffer);
            long val = long.Parse(valStr);
        }
        Console.WriteLine (sw.ElapsedMilliseconds);
    }
}

static class BufferToLong
{

    public static long GetValue(Byte[] buffer) {

        long number = 0;

        foreach (byte currentByte in buffer) {

            char currentChar = (char)currentByte;
            int currentDigit = currentChar - '0';

            number *= 10 ;
            number += currentDigit;

        }

        return number;
    }

}
于 2013-01-19T09:49:39.767 に答える