StephenWinburn
StephenWinburn

Reputation: 107

Comparing Math.Log and Math.Pow

I am working with annuities and have the following methods in my code:

public static double NumPMTsRemaining( double CurBalance, double ContractRate, double Pmt)
{
    double rt = PeriodicRate(ContractRate);
    return -1 * Math.Log(1 - (CurBalance * (rt) / Pmt)) / Math.Log(1 + (rt));
}

public static double MonthlyPMT(double OrigBalance, double ContractRate, int Term)
{
    double rt = PeriodicRate(ContractRate);
    if (ContractRate > 0)
        return (OrigBalance * rt * Math.Pow(1 + rt, Term)) / (Math.Pow(1 + rt, Term) - 1);
    else return OrigBalance / Term;
}

I use the former method to determine if the payment for a loan will insure the loans pays off in its life remaining. I use the latter method to determine if a payment is quoted for a payment period other than monthly and then replace it with a monthly payment if so. Upon reflection I can use the latter method for both tasks.

With that in mind, I was wondering if anyone knew off the top of their head if Math.Pow is faster/more efficient than/relative to Math.Log?
I assume that Math.Pow is the better choice, but would appreciate a bit of input.

Upvotes: 3

Views: 1180

Answers (1)

StephenWinburn
StephenWinburn

Reputation: 107

I have built a benchmark as recommended by @Mangist. The code is posted below. I was surprised by the response by @CodesInChaos. I, of course, did some research and realized I could improve a large amount of my code. I will post a link to a interesting StackOverflow article I found in this regard. A number of people had worked out improvements on Math.Pow due to the aforementioned fact.

Thank you again for the suggestions and information.

        int term = 72;
        double contractRate = 2.74 / 1200;
        double balance = 20203.66;
        double pmt = 304.96;
        double logarithm = 0;
        double power = 0;

        DateTime BeginLog = DateTime.UtcNow;
        for (int i = 0; i < 100000000; i++)
        {
            logarithm=(-1*Math.Log(1-(balance*contractRate/pmt))/Math.Log(1+contractRate));
        }
        DateTime EndLog = DateTime.UtcNow;
        Console.WriteLine("Elapsed time= " + (EndLog - BeginLog));
        Console.ReadLine();

        DateTime BeginPow = DateTime.UtcNow;
        for (int i = 0; i < 100000000; i++)
        {
            power = (balance * contractRate * Math.Pow(1 + contractRate, term)) / (Math.Pow(1 
                      +  contractRate, term) - 1);
        }
        DateTime EndPow = DateTime.UtcNow;
        Console.WriteLine("Elapsed time= " + (EndPow - BeginPow));
        Console.ReadLine();

The results of the benchmark were Elapsed time for the logarithm 00:00:04.9274927 Elapsed time for the power 00:00:11.6981697

I also alluded to some additional StackOverflow discussions which shed light on the comment by @CodeInChaos.

How is Math.Pow() implemented in .NET Framework?

Let me add a head to head comparison between a suggestion on the above link and the Math.Pow function. I benchmarked Math.Pow(x,y) against Math.Exp(y*Math.Log(x)) with the following code:

        DateTime PowBeginTime = DateTime.UtcNow;
        for (int i = 0; i < 250000000; i++)
        {
            Math.Pow(1 + contractRate, term);
        }
        DateTime PowEndTime = DateTime.UtcNow;
        Console.WriteLine("Elapsed time= " + (PowEndTime - PowBeginTime));
        Console.ReadLine();

        DateTime HighSchoolBeginTime = DateTime.UtcNow;
        for (int i = 0; i < 250000000; i++)
        {
            Math.Exp(term * Math.Log(1 + contractRate));
        }
        DateTime HighSchoolEndTime = DateTime.UtcNow;
        Console.WriteLine("Elapsed time= " + (HighSchoolEndTime - HighSchoolBeginTime));
        Console.ReadLine();

The results were: Math.Pow(x,y) 00:00:19.9469945 Math.Exp(y*Math.Log(x)) 00:00:18.3478346

Upvotes: 2

Related Questions