我需要计算算法在没有实际运行代码的情况下花费的大概时间。
我实际上无法让完整的算法运行,因为根据硬件需要数天或数周才能完成。该算法本质上是对数的。以下是算法的估计。当然,这里没有逻辑。
我们从[n]
的力量开始,其中[n]
是大数字。
int baseTwo = 2;
double log = 0D;
BigInteger number = 0;
double exponent = 5000000; // 5,000,000.
while (exponent > 0)
{
number = BigInteger.Pow(baseTwo, (int) exponent); // [baseTwo]=2 raised to the power [exponent].
number = this.ProcessNumber(number, baseTwo); // Returned number will be slightly smaller than what went in.
exponent = BigInteger.Log(number, baseTwo); // The Base 2 Log to calculate the slightly decreased exponent (if exponent was 38762, then the result would be 38761.4234 for example).
}
private BigInteger ProcessNumber(BigInteger number)
{
double rand = 0;
BigInteger result = 0;
rand = Random.Next(51, 100) / 100D; // Anywhere between 51% to 99%.
result = number * rand; // [result] will always be less than [number] but more than half of [number].
return (result);
}
由于指数向零迭代,每次迭代的时间自然从一次迭代减少到下一次迭代。
答案 0 :(得分:3)
即使您知道算法的限制性大O效率,第一次也是最后一次迭代都不会为您提供足够的信息,因为无法保证每次迭代的时间精确到达限制效率。例如,如果你的函数是大n的限制中的O(n ^ 2)(我知道它不是在这种情况下 - 但这仅仅是为了说明),而是实际代码的每一步的实际时间有点像1 * log(n)+ 10 ^ -6 * n + 10 ^ -24 * n ^ 2,你可能不会看到 n ^ 2在你选择的n范围内的行为在。所以你会在第一次和最后一次迭代中得到两个点,但无法知道如何在它们之间画线。
您可以按照建议定期对数据进行采样,然后将其导出以进行拟合和/或数值积分。但是,假设你只需知道大致的总时间(或许+/- 10%)就应该做足够的事情...... 伪代码:
totaltime = 0;
for i := 0 to 5 do
begin
starttime = now;
for j := 0 to 10 do
run algorithm(i*10^6+j)
endtime = now;
totaltime := totaltime + 10^5*(endtime - starttime);
writeln('10 iterations near ', i*10^6, ' takes ', endtime - starttime, ' seconds');
end;
writeln('approximate time for complete algorithm to run is', totaltime);
..并在比我写这篇文章更短的时间内得到答案。
答案 1 :(得分:1)
我建议你的算法很小但输入量增加,并做一个图表。
图表上的曲线可能会突然发生变化,但它们可能仍然比许多类似的背包计算更好。