好的,这有点奇怪。我有一个算法来找到最高可能的数值回文,它是两个因子的倍数,每个因子都有K个数字。
用于找到最高有效回文的方法是查看数字集的最高可能回文(即,如果k = 3,则最高可能是999999,然后是998899等)。然后我检查回文是否有两个K位数因子。
对于调试,我认为将每个我正在检查的回文打印到控制台是个好主意(以确保我得到它们。令我惊讶的是,添加
Console.WriteLine(palindrome.ToString());
每次迭代找到一个回文都会使我的运行时间从大约24秒减少到大约10秒~14。
要验证,我多次运行该程序,然后注释掉Console命令并运行了几次,每次使用控制台命令时更短
。这看起来很奇怪,有什么想法吗?
如果有人想对此进行打击,那么这就是来源:
static double GetHighestPalindromeBench(int k)
{
//Because the result of k == 1 is a known quantity, and results in aberrant behavior in the algorithm, handle as separate case
if (k == 1)
{
return 9;
}
/////////////////////////////////////
//These variables will be used in HasKDigitFactors(), no need to reprocess them each time the function is called
double kTotalSpace = 10;
for (int i = 1; i < k; i++)
{
kTotalSpace *= 10;
}
double digitConstant = kTotalSpace; //digitConstant is used in HasKDigits() to determine if a factor has the right number of digits
double kFloor = kTotalSpace / 10; //kFloor is the lowest number that has k digits (e.g. k = 5, kFloor = 10000)
double digitConstantFloor = kFloor - digitConstant; //also used in HasKDigits()
kTotalSpace--; //kTotalSpace is the highest number that has k digits (e.g. k = 5, kTotalSpace = 99999)
/////////////////////////////////////////
double totalSpace = 10;
double halfSpace = 10;
int reversionConstant = k;
for (int i = 1; i < k * 2; i++)
{
totalSpace *= 10;
}
double floor = totalSpace / 100;
totalSpace--;
for (int i = 1; i < k; i++)
{
halfSpace *= 10;
}
double halfSpaceFloor = halfSpace / 10; //10000
double halfSpaceStart = halfSpace - 1; //99999
for (double i = halfSpaceStart; i > halfSpaceFloor; i--)
{
double value = i;
double palindrome = i;
//First generate the full palindrome
for (int j = 0; j < reversionConstant; j++)
{
int digit = (int)value % 10;
palindrome = palindrome * 10 + digit;
value = value / 10;
}
Console.WriteLine(palindrome.ToString());
//palindrome should be ready
//Now we check the factors of the palindrome to see if they match k
//We only need to check possible factors between our k floor and ceiling, other factors do not solve
if (HasKDigitFactors(palindrome, kTotalSpace, digitConstant, kFloor, digitConstantFloor))
{
return palindrome;
}
}
return 0;
}
static bool HasKDigitFactors(double palindrome, double totalSpace, double digitConstant, double floor, double digitConstantFloor)
{
for (double i = floor; i <= totalSpace; i++)
{
if (palindrome % i == 0)
{
double factor = palindrome / i;
if (HasKDigits(factor, digitConstant, digitConstantFloor))
{
return true;
}
}
}
return false;
}
static bool HasKDigits(double value, double digitConstant, double digitConstantFloor)
{
//if (Math.Floor(Math.Log10(value) + 1) == k)
//{
// return true;
//}
if (value - digitConstant > digitConstantFloor && value - digitConstant < 0)
{
return true;
}
return false;
}
请注意,我在HasKDigits中注释了Math.Floor操作。当我试图确定我的数字检查操作是否比Math.Floor操作更快时,这一切都开始了。谢谢!
编辑:函数调用
我使用StopWatch来测量处理时间。我还使用物理秒表来验证StopWatch的结果。
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
double palindrome = GetHighestPalindromeBench(6);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}:{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
Console.WriteLine();
Console.WriteLine(palindrome.ToString());
Console.WriteLine();
Console.WriteLine(elapsedTime);
答案 0 :(得分:4)
我已经测试了你的代码。我的系统是i7-3770 3.40 GHz,具有超线程的四核,因此可以使用8个内核。
使用和不使用控制台Writeline语句(已注释或未注释)的调试版本,无论是否在调试模式下,时间从大约8.7秒到9.8秒不等。作为发布版本,无论哪种方式都可以达到大约6.8-7.0秒。 VS内部和命令行中的数字相同。所以你的观察不会再现。
在没有控制台输出的性能监视器上,我看到一个核心为100%,但它在核心1,4,5和8之间切换。没有控制台输出,其他核心上就有活动。最大CPU使用率永远不会超过18%。
根据我的判断,你的控制台输出数字可能与我的一致,并代表真正的价值。所以你的问题应该是:为什么你的系统在没有控制台输出的情况下这么慢?
答案是:因为您的计算机或项目存在一些我们不了解的不同之处。我之前从未见过这个,但是有些东西正在吸收循环,你应该能够找到它是什么。
我已经写过这个作为答案,虽然它不是一个真正的答案。如果你得到更多的事实并更新你的问题,希望我能提供更好的答案。