これまでの回答
というわけでコードの内訳です。
//Time: ~7s (linear loop algorithm)
//100,000! (456,574 decimal digits)
BigInteger bigIntVar = computeFactorial(100000);
//The first three here are just for comparison and are not actually Base 10.
bigIntVar.ToBase64String() //Time: 00.001s | Base 64 | Tetrasexagesimal
bigIntVar.ToString("x") //Time: 00.016s | Base 16 | Hexadecimal
bigIntVar.ToBinaryString() //Time: 00.026s | Base 02 | Binary
bigIntVar.ToQuickString() //Time: 11.200s | Base 10 | String Version
bigIntVar.ToQuickString() //Time: 12.500s | Base 10 | StringBuilder Version
bigIntVar.ToString() //Time: 13.300s | Base 10 | Original
元の質問のもの
私はこれに多くの時間を費やしたので、あなたの助けが必要です.
これは巨大な階乗を計算するための個人的なプロジェクトです (例: 100,000!)
これが私のコードです:
using (var stream = new StreamWriter(fileName + ".txt", false))
{
stream.WriteLine(header);
var timer = new Stopwatch();
timer.Restart();
//This is the huge BigInteger holding the answer to 100,000!
stream.WriteLine(saveFactorial.Output.ToString());
//Let me be clear: ToString() is directly causing the the 13sec time delay.
//Not the stream.
timer.Stop();
}
time = (timer.ElapsedMilliseconds / 1000.0).ToString() + "s";
MessageBox.Show(time);
10万で!私のマシンでは、計算に約7秒かかります(線形ループアルゴリズム)。
しかし、この標準 IO コードでは、保存に 13 秒かかります。
つまり、適度に計算するよりも作業を保存する方が時間がかかります。
だから私は多分私が使うことができると思った:
BigInteger.ToByteArray();
これは非常に高速に実行されますが、読み取り可能なテキストに保存する方法がわかりませんでした。
上記の方法を使用して、この自作の拡張子を持つテキスト ファイルにバイナリ文字列を書き込むことができます。
ToBinaryString
//Usage: string bigIntBinary = bigIntVar.ToBinaryString();
public static string ToBinaryString(this BigInteger source)
{
//If you lookup the ToByteArray() method...
//It actually stores the bytes in reverse order.
var bigIntBytes = source.ToByteArray().Reverse();
StringBuilder bigIntBinary = new StringBuilder();
foreach (var bigIntByte in bigIntBytes)
{
bigIntBinary.Append(Convert.ToString(bigIntByte, 2).PadLeft(8, '0'));
}
return bigIntBinary.ToString();
}
ToBase64String
////Usage: string bigIntBase64 = bigIntVar.ToBase64String();
public static string ToBase64String(this BigInteger source)
{
var bigIntBytes = source.ToByteArray().Reverse().ToArray();
return Convert.ToBase64String(bigIntBytes);
}
各桁を取得するために数学的な方法(mod 10など...)も試しましたが、ToString()よりもTON時間がかかります。
ここで何が間違っていますか?
このコードは、以下の回答に基づいて思いついたものです。これは ToString() よりも高速ですが、数秒しかかかりません。
ToQuickString
//Usage: string bigIntString = bigIntVar.ToQuickString()
public static String ToQuickString(this BigInteger source)
{
powersOfTen = new List<BigInteger>();
powersOfTen.Add(1);
for (BigInteger i = 10; i < source; i *= i)
{
powersOfTen.Add(i);
}
return BuildString(source, powersOfTen.Count - 1).ToString().TrimStart('0');
}
private static List<BigInteger> powersOfTen;
private static string BuildString(BigInteger n, int m)
{
if (m == 0)
return n.ToString();
BigInteger remainder;
BigInteger quotient = BigInteger.DivRem(n, powersOfTen[m], out remainder);
return BuildString(quotient, m - 1) + BuildString(remainder, m - 1);
}