这个小型控制台应用程序会计算一个BigInteger并给我一个反馈,它指向它所指向的指数。
现在我对一些速度提升感到好奇。我该怎么办?
感谢您的推荐!
using System;
using System.Collections.Generic;
using System.Numerics;
namespace Counter
{
internal class Program
{
private static readonly Dictionary<BigInteger, int> Dic = new Dictionary<BigInteger, int>();
private static void Main(string[] args)
{
Console.WriteLine("Start with counting ... from 1 to 2^256.");
Console.WriteLine();
CreateDict();
var bigInteger = new BigInteger();
Console.WriteLine("D:HH:mm:ss,ms - fac. - Number");
Console.WriteLine("---------------------------------------------------");
var startTime = DateTime.UtcNow;
while (true)
{
bigInteger++;
if (Dic.ContainsKey(bigInteger))
{
Console.WriteLine("{0:G} - 2^{1,3} = {2:#,0}", (DateTime.UtcNow - startTime), Dic[bigInteger], bigInteger);
}
}
}
private static void CreateDict()
{
for (int i = 1; i <= 256; i++)
{
Dic.Add(BigInteger.Pow(2, i), i);
}
}
}
}
输出:http://pastebin.com/bMBntFsL
进度
使用BigInteger并不是那么好。
BigInteger 2 ^ 26 = 5s
Double 2 ^ 26 = 1,3s
从Dict切换到直接比较要快得多
int i = 1;
double pow = Math.Pow(2, i);
while (true)
{
bigInteger++;
if (bigInteger == pow)
{
Console.WriteLine("{0:G} - 2^{1,3} = {2:#,0}", (DateTime.UtcNow - startTime), Dic[bigInteger], bigInteger);
i++;
pow = Math.Pow(2, i);
}
}
Dict 2 ^ 26 = 1,3s
&#34;&LT;&#34; 2 ^ 26 = 0,5s
答案 0 :(得分:2)
如果确实想要在循环中计算最多2 ^ 256,请不要使用BigInteger
。
来自MSDN:
.NET Framework中的其他数字类型也是不可变的。但是,由于BigInteger类型没有上限或下限,因此其值可能会变得非常大并且会对性能产生可测量的影响。
虽然此过程对调用方是透明的,但确实会导致性能损失。在某些情况下,特别是在非常大的BigInteger值的循环中执行重复操作时,性能损失可能显着
由于您所需的值很大但非常大,您可以改用double
。 double
值可以达到1.7 × 10^308
,因此您可以使用2 ^ 256(1.15 × 10^77
)。这对应用程序的性能有很大帮助。
另一项改进是将TryGetValue
用于您的词典,而不是ContainsKey
,正如您在this answer中所看到的那样。
因为您同时执行ContainsKey(bigInteger)
和Dic[bigInteger]
,所以您要进行两次查找。
所以代码将成为:
while (true)
{
bigValue++;
int exponent;
if (Dic.TryGetValue(bigValue, out exponent))
{
Console.WriteLine("{0:G} - 2^{1,3} = {2:#,0}", (DateTime.UtcNow - startTime), exponent, bigValue);
}
}