【问题标题】:How to Improve runtime for Iterative Function如何改进迭代函数的运行时间
【发布时间】:2014-11-20 16:12:33
【问题描述】:

我的代码运行时间变得很长,它可能需要迭代 30,000 次,这在我的计算机上大约需要 30 秒,但在客户端上需要更长的时间。我想知道是否可以得到任何提示来加快计算速度。迭代函数必须使值尽可能接近零,并且它会减小或增加,直到满足条件。我通过增加 1 美元来加速它,然后当它接近范围时,它增加 0.1 美元以提高精度。

我把它分解成节点。有一个初始节点,然后它检查左节点的差异,然后检查右节点的差异。哪个会产生较小的差异,它会朝那个方向前进,直到差异尽可能小。

//Current Node
double InitialFinalPayment = bruteforceFlexibleAmortization(0);
double intialPaymentAmount = Calc_Payment(Findper() - FindSkipNMonths(), Findnint(),
                                             Findpv() + InterestPaid, Findfv(), Findcf(), Findpf(), Finddisc(),
                                             Findbep()), 2);
double diffInitial = Math.Abs(intialPaymentAmount - InitialFinalPayment);

decimal runningIncrement = 1M;
double nextPayment       = 0;

//Node Ahead
Double incrementOutcome = bruteforceFlexibleAmortization(runningIncrement);
Double incrementPayment = intialPaymentAmount       + (double)runningIncrement;
Double diffincrement    = Math.Abs(incrementPayment - incrementOutcome);

//Node Behind
Double decrementOutcome = bruteforceFlexibleAmortization(-runningIncrement);
Double decrementPayment = intialPaymentAmount       - (double)runningIncrement;
Double diffdecrement    = Math.Abs(decrementPayment - decrementOutcome);

if (diffincrement < diffInitial)
{
    runningIncrement += 1.0M;
    double nextValue = bruteforceFlexibleAmortization(runningIncrement);
    nextPayment       = intialPaymentAmount + (double)runningIncrement;
    double diffNext = Math.Abs(nextPayment  - nextValue);
    while (diffNext < diffdecrement)
    {
         diffdecrement     = diffNext;
         runningIncrement += 1.0M;
         nextValue         = bruteforceFlexibleAmortization(runningIncrement);
         nextPayment       = intialPaymentAmount  + (double)runningIncrement;
         diffNext          = Math.Abs(nextPayment - nextValue);
    }
    diffincrement     = diffNext;
    runningIncrement -= 0.01M;
    nextValue         = bruteforceFlexibleAmortization(runningIncrement);
    nextPayment       = intialPaymentAmount  + (double)runningIncrement;
    diffNext          = Math.Abs(nextPayment - nextValue);

    while (diffNext < diffincrement)
    {
         diffincrement     = diffNext;
         runningIncrement -= 0.01M;
         nextValue         = bruteforceFlexibleAmortization(runningIncrement);
         nextPayment       = intialPaymentAmount  + (double)runningIncrement;
         diffNext          = Math.Abs(nextPayment - nextValue);
    }
    return nextPayment + (double)0.01M;
}

else if (diffdecrement < diffInitial)
{
     runningIncrement += 1.0M;
     double nextValue  = bruteforceFlexibleAmortization(-runningIncrement);
     nextPayment       = intialPaymentAmount - (double)runningIncrement;
     double diffNext = Math.Abs(nextPayment  - nextValue);
     while (diffNext < diffdecrement)
     {
         diffdecrement     = diffNext;
         runningIncrement += 1.0M;
         nextValue         = bruteforceFlexibleAmortization(-runningIncrement);
         nextPayment       = intialPaymentAmount  - (double)runningIncrement;
         diffNext          = Math.Abs(nextPayment - nextValue);
     }
     diffincrement     = diffNext;
     runningIncrement -= 0.01M;
     nextValue         = bruteforceFlexibleAmortization(-runningIncrement);
     nextPayment       = intialPaymentAmount  - (double)runningIncrement;
     diffNext          = Math.Abs(nextPayment - nextValue);

     while (diffNext < diffincrement)
     {
          diffincrement     = diffNext;
          runningIncrement -= 0.01M;
          nextValue         = bruteforceFlexibleAmortization(-runningIncrement);
          nextPayment       = intialPaymentAmount  - (double)runningIncrement;
          diffNext          = Math.Abs(nextPayment - nextValue);
     }
     return nextPayment - (double)0.01M;
     }
return InitialFinalPayment;
}

我唯一的想法是通过增加/减少运行增量以成为一个更大的值,并随着它接近该值而使该值变小。就像它是 1 然后 0.1,可能是 10 然后 1 然后 0.1 但它绝对不会是干净的代码

【问题讨论】:

  • 嗯,你的 bruteforceFlexibleAmortization 看起来很可疑。
  • 您是否尝试分析您的方法以找出需要这么长时间的部分?
  • @MarcinJuraszek 这是 while 语句。当它必须减少/增加 1 时。
  • 你确定没有更有效的方法来计算所涉及的数学吗?
  • 您应该深入研究。您的 while 循环在其中做了很多事情。顺便提一句。您可以尝试乘法/除法而不是加法/减法吗?例如,从乘以 2 开始。现在太大了吗?进入最后 2 个值之间 ((current+lastLower)/2)。现在太低了?获取(current+lastGreater)/2。类似于二进制搜索的工作方式。真的很难通过想法给你其他任何东西,因为我们不知道你的代码试图实现什么。

标签: c#


【解决方案1】:

如果您的bruteforceFlexibleAmortizationmonotonic,您应该尝试使用二分搜索使用的类似方法,而不是始终将您的输入更改为相同的值。

var currentValue = 50;
var lastLower = 0;
var lastGreater = 100;

do
{
    var currentResult = calculateResult(initialValue);

    if(currentResult < expectedResult)
    {
        lastLower = currentValue;
        currentValue = (currentValue + lastGreater) / 2;
    }
    else
    {
        lastGreater = currentValue;
        currentValue = (currentValue + lastLower) / 2;
    }
} while (Math.Abs(currentResult - expectedResult) < epsilon)

这对你来说会有点不同,因为你需要调用 2 个方法,但你应该明白这一点。

例如如果您尝试使用您的方法将给定n 的平方根插值到一定精度,那将非常慢。使用类似二进制的方法,您可以获得更多的迭代来获得紧密的插值。

【讨论】:

  • 顺便说一句。让我知道该解决方案的速度有多快。我很好奇:)
猜你喜欢
  • 2011-10-20
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2017-09-25
  • 2016-03-26
  • 2020-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多