如何改进迭代函数的运行时间

时间:2014-11-20 16:12:33

标签: c#

我的代码运行时间越来越长,它必须迭代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但它绝对不会是干净的代码

1 个答案:

答案 0 :(得分: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种方法,但你应该明白这一点。

e.g。如果您尝试使用您的方法将给定n的平方根插值到某个精度,那将非常慢。使用二进制类,您可以获得更多迭代以进行近似插值。