Tuesday, April 5, 2011

Raising a decimal to a power of decimal ?

The .net framework provides in the Math class a method for powering double. But by precision requirement I need to raise a decimal to a decimal power [ Pow(decimal a, decimal b) ]. Does the framework have such a function? Does anyone know of a library with this kind of function?

From stackoverflow
  • Are you sure you actually want to do this? A decimal multiply is about 40 times slower than double's, so I'd expect a decimal Math.Pow() to be practically unusable.

    If you expect only integer powers, though, I suggest you use the integer-based power algorithm that was already discussed here on SO.

    duffymo : "unusable"? Decimals raised to decimal powers are common in scientific computing (e.g., relationships between Nusselt, Reynolds, and Prandtl numbers in fluid mechanics). I doubt that it'll be a problem.
    Christoph Rüegg : Hardly - that would be the first time I've heard of anyone using a base-10 type like System.Decimal for scientific computations. Especially not in any area related to physics, like fluid mechanics. What is so special about these relationships that requires a base-10 type?
    P Daddy : @Christoph: I'd point out that most calculators (hardware and software) use base-10 computation.
    P Daddy : @duffymo: I, too, would expect a Pow(decimal, decimal) function to perform a few orders of magnitude slower than Pow(double, double), owing largely to the fact that the FPU cannot be utilized for decimals...
    P Daddy : ... Whether or not this would classify it as "unusable" depends on how many such calculations one expected to do in a given amount of time.
  • I think it depends a lot on the number you plan on plugging in. If 'a' and 'b' are not 'nice' number then you'll likely get a value which is non-terminating that is impossible to store and if C# BigDecimal behaves at all like Java BigDecimal it probably throws an exception in such a case.

  • log(c^d) = d * log(c)

    further...

    c^d = antilogarithm(d * log(c))

    Code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("169^(1/2) = " + RaiseToPower((169), (.5)));
                Console.ReadLine();
            }
    
            public static double RaiseToPower(double a, double b)
            {
                return Math.Exp(b * Math.Log(a));
            }
        }
    }
    
    Christoph Rüegg : The framework provides neither Log/Ln nor Exp for System.Decimal (remember, decimal is NOT intended for scientific computations).
    Chris Ballance : The question asked how to raise a decimal to a decimal power. No one mentioned a need for floating-point precision
    P Daddy : The question specifically mentions "Pow(decimal a, decimal b)".
    norheim.se : In what way would you say this solution is better than just using the framework's Math.Pow function? Both take doubles as input and return doubles. Neither handles System.Decimal.
  • To solve my problem I found some expansion series, and them I had them implemented to solve the equation X^n = e^(n * ln x).

      // power series
      int iteration = 27; // Adjust this to modify the precision
      decimal result = 1; 
      while (iteration > 0)
      {
        fatorial = Factorial(iteration);
        result += (Pow(power, iteration) / fatorial);
        iteration--;
      }
    
      // natural logarithm series
      decimal aux = (value - 1);
      decimal result = 0;
      while (iteration > 0)
      {
        result += Pow(aux, iteration) / iteration;
        iteration--;
      }
    

    The Pow() and Factorial() functions are simple because the power is always an int (inside de power series).

0 comments:

Post a Comment