1

入力用と出力用の 2 つのテキスト ボックスがあります。入力から 16 進文字のみをフィルタリングし、大文字で出力する必要があります。正規表現 ( Regex) を使用すると、ループを使用するよりもはるかに高速であることを確認しました。

最初に大文字にする私の現在のコードは、次のように16進数をフィルタリングします。

string strOut = Regex.Replace(inputTextBox.Text.ToUpper(), "[^0-9^A-F]", "");
outputTextBox.Text = strOut;

別の方法:

string strOut = Regex.Replace(inputTextBox.Text, "[^0-9^A-F^a-f]", "");
outputTextBox.Text = strOut.ToUpper();

入力には最大 32k 文字を含めることができるため、ここでは速度が重要です。以前TimeSpanは測定していましたが、結果に一貫性がありません。

私の質問は、どのコードがより高速なパフォーマンスを発揮し、その理由は何ですか?

4

3 に答える 3

3

これは間違いなく時期尚早の最適化のケースです。32K 文字は、最新のコンピューターで実行される細かく調整された正規表現エンジンにとって大した問題ではないため、この最適化タスクはほとんど理論的なものです。

^パフォーマンスについて議論する前に、式が出力に文字を許可するため、おそらく期待どおりに動作していないことを指摘しておく価値があります。[^0-9A-F]代わりにandを使用する必要があります[^0-9A-Fa-f]

文字クラスの文字数はほとんど変わらないため、2 つの正規表現の速度は同じになります。ただし、無効な文字がすべて削除されるため、2 番目の組み合わせToUpper呼び出しは短い可能性のある文字列に対して呼び出されます。したがって、2 番目のオプションは潜在的にわずかに高速です。

ただし、これを最後の CPU サイクルに最適化する必要がある場合は、正規表現を使用せずにこれを書き直して、ToUpper: ループ内の入力文字列をウォークスルーし、有効なすべての文字を追加しStringBuilderます。小文字が表示されたら、大文字に変換します。

于 2013-05-29T01:05:36.073 に答える
1

テストは簡単です:

using System;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string letters = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ";
            Random random = new Random();
            string[] strings = Enumerable.Range(0, 5000).Select(i1 => string.Join("", Enumerable.Range(0,32000).Select(i2 => letters[random.Next(0, letters.Length - 1)]))).ToArray();

            Stopwatch stopwatchA = new Stopwatch();
            stopwatchA.Start();

            foreach (string s in strings)
                Regex.Replace(s.ToUpper(), "[^0-9^A-F]", "");

            stopwatchA.Stop();

            Stopwatch stopwatchB = new Stopwatch();
            stopwatchB.Start();

            foreach (string s in strings)
                Regex.Replace(s, "[^0-9^A-F^a-f]", "").ToUpper();

            stopwatchB.Stop();

            Debug.WriteLine("stopwatchA: {0}", stopwatchA.Elapsed);
            Debug.WriteLine("stopwatchB: {0}", stopwatchB.Elapsed);
        }
    }
}

実行 1:

ストップウォッチA: 00:00:39.6552012

ストップウォッチB: 00:00:40.6757048

実行 2:

ストップウォッチA: 00:00:39.7022437

ストップウォッチ B: 00:00:41.3477625

実行するものでは、最初のアプローチの方が高速です。

于 2013-05-29T01:18:56.860 に答える