Ответы до сих пор
Итак, вот расшифровка кода.
//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);
На 100 000! на моей машине требуется около 7 секунд для вычисления (алгоритм линейного цикла).
Тем не менее, с этим стандартным кодом ввода-вывода для сохранения требуется 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);
}
Я также попробовал математический способ (мод 10 и т. д.), чтобы получить каждую цифру, но это занимает ТОННУ больше времени, чем ToString().
Что я здесь делаю неправильно?
Этот код - это то, что я придумал на основе ответа ниже. Это быстрее, чем 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);
}
ToString
занимает довольно много времени, но если вы хотите, чтобы файл был удобочитаемым, вы мало что можете с этим поделать. - person Rawling   schedule 31.10.2012.ToString("x")
намного быстрее. - person Rawling   schedule 31.10.2012.ToString("X")
)) формате :) Потому что никто не собирается его читать, верно? - person flindeberg   schedule 31.10.2012