2016-09-21 4 views
0

doubleの値が何百万もの大規模なCSVのようなファイルを書くと、ボトルネックは二重からストリングへの変換のようです。最速の二重ストリング変換

StreamWriterに二重の値を追加する最も早い方法は、ポイントの後に固定された桁数を使用しますか?

現在、私は私が代わりに、二重の文字列定数を記述する場合、プログラムが速く10回を終了

// called once 
System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo(); 
nfi.NumberDecimalDigits = 4; 

// called millions of times in a loop 
streamwriter.Write(mydouble.ToString(nfi)); 

を使用しています。
doubleの代わりにintを書くと、それはまだ2倍以上の速さです。
(すべてのテストはデバッガを接続せずにリリースモードで実行されました)

このダブルを文字列に変換する最も速い方法は何ですか?


私は以下の私の問題を説明するためのベンチマークが含まれている:

私は、行の100倍、ファイルへの100万倍を書きます。

合計時間は25.2秒です。 double.ToStringのみのループで、streamwriter.Writeは21秒で終了しません。 のみstreamwriter.Writeとのループは、文字列に二重の変換3.5秒

System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo(); 
nfi.NumberDecimalDigits = 4; 
double d = 0.1234; 
Stopwatch watch; 

watch = Stopwatch.StartNew(); 
for (int i = 0; i < 100; i++) 
{ 
    using (StreamWriter sw = new StreamWriter(@"c:\temp\test.txt", false, Encoding.UTF8, 65536)) 
    { 
     for (int j = 0; j < 1000000; j++) 
     { 
      sw.Write(d.ToString(nfi)); 
     } 
    } 
} 
Console.WriteLine("stream.Write & double.ToString: {0}", watch.ElapsedMilliseconds); 

watch = Stopwatch.StartNew(); 
for (int i = 0; i < 100; i++) 
{ 
    using (StreamWriter sw = new StreamWriter(@"c:\temp\test.txt", false, Encoding.UTF8, 65536)) 
    { 
     for (int j = 0; j < 1000000; j++) 
     { 
      sw.Write("0.1234"); 
     } 
    } 
} 
Console.WriteLine("only stream.Write: {0}", watch.ElapsedMilliseconds); 

watch = Stopwatch.StartNew(); 
for (int i = 0; i < 100; i++) 
{ 
    using (StreamWriter sw = new StreamWriter(@"c:\temp\test.txt", false, Encoding.UTF8, 65536)) 
    { 
     for (int j = 0; j < 1000000; j++) 
     { 
      string s = d.ToString(nfi); 
     } 
    } 
} 
Console.WriteLine("only double.ToString: {0}", watch.ElapsedMilliseconds); 
+0

興味深い:[ここ](http://cc.davelozinski.com/c-sharp/fastest-way- to-string-to-string)、int型の文字列変換のテストが行​​われ、 'ToString()'が最も優れていることが判明しました。 –

+0

私は前に他のメソッドのいくつかを試しました。以前はString.Formatを使用していましたが、double.ToStringは高速に見えました。しかし、私はまだもっと良い方法を見つけようとしています。このような操作は、ディスクの速度ではなく、ファイルを書き込む際のボトルネックとなるのが奇妙です。 – HugoRune

+0

アプリケーションがDEBUGまたはRELEASEを使用して構築されている場合、速度は異なります。リリースでは、組み込みコプロセッサを使用して浮動小数点演算を行い、DEBUGはコプロセッサをシミュレートします。 – jdweng

答えて

1

で終わる複雑な問題であり、あなたはダブルスの多くを変換する必要がある場合には、巨大なパフォーマンスキラーことができます。あなたの唯一のオプションは、.NETバージョンがあなたにとって遅すぎる場合や、まったく変換しない場合(および問題を解決する別の方法を見つける場合)、より優れた/より速い変換関数を実装することです。

高速変換のために、Florian Loitschによって導入された高速変換アルゴリズムのC#バージョンGrisuを試してみるとよいでしょう。あなたは4小数点書式を自分で適用する必要がありますが、それは簡単な文字列操作で行うことができます。

このjava based approachは、独自のバージョンをビルドしたい場合(いくつかの数字から特定のプロパティを使用することもできます)、いくつかの洞察を与えるかもしれません。

1

一般的なdouble-to-stringコンバーターは、NaN、超大数、超小数のようなあらゆる種類のエッジケースを注意しなければならず、オンザフライで何桁の数字小数点以下を保持する。

数字の範囲がわかっている場合は、さまざまな部分を整数に変換することで、自分でやることができます。 (Cで)例えば:

bool bNegative = false; 
if (v < 0){v = -v; bNegative = true;} // make v >= 0 
double fv = floor(v); // get integer part as double 
int i = (int)fv;  // get integer part as integer 
int f = (int)floor((v - fv)*1000.0); // get fraction thousandths as integer 
// print the integer and the fractional thousandths, both as integers 
if (bNegative){ 
    fprintf(file, "-%d.%03d", i, f); 
} else { 
    fprintf(file, "%d.%03d", i, f); 
} 

またはそれらの線に沿って何か...

+0

興味深い考えですが、私の最初のテストは、2つの整数を書き出し、コンバージョンは実際にはC#で単一のdoubleを書くよりも遅いです。 – HugoRune

+0

@HugoRune:大きなファイルを処理しなければならないときは、人はそれを読んでいないことを知っているので、バイナリで書き込み/読み込みを行います。より高速で正確です。 SASはこの前にこれを知っていたので、「SAS Transport Format」または「xpt」と呼ばれるものを定義しました。 –

関連する問題