Results 1 to 10 of 10

Thread: Exp series error term help (probably easy for people who know calc)

  1. #1

    Thread Starter
    Addicted Member Latin4567's Avatar
    Join Date
    Jan 2005
    Posts
    202

    Question Exp series error term help (probably easy for people who know calc)

    I'm extending j#'s built in BigInteger and BigDecimal classes to have proper operators and standard math functions like sqrt, log, exponentiation with decimal powers, trig functions, etc, in Vb.net... I already have logs and nth roots and nth powers done, and I implemented the super fast karatsuba multiplication algorithim, and a very very fast factorial algorithim....

    I need a FAST Exp(x) (e^x) routine so I can define exponentiation with decimal/irrational powers.

    I'm using the series deffinition of e^x

    e^x = SUM TO INFINITY OF x^n/n!

    It works, but I can't figure out the exact correlation between number of iterations and error... like I need to know, given an X value of relatively arbitrary magnitude (within reason), and a specified precision to a certain number of decimal points, how high of an N value I will need to go before the series converges on a correct sum to that degree of precision

    please advise

  2. #2
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: Exp series error term help (probably easy for people who know calc)

    I would be shocked if that series definition converges more quickly than some clever algorithm. Off the top of my head you could use exponentiation by squaring to quickly find e^n's, perhaps using the series for the fractional part of the exponent. For small x (< 1 in magnitude) the series would converge quite quickly.

    Lemme think... for |x| < 1, take the ith partial sum Pi (sum from n=0 to i-1 of x^n/n!) which must itself be less than the sum from n=0 to i-1 of 1^n/n! = sum of 1/n!. The correction term is similarly bounded and gives...

    e^x - Pi = sum from n=i to infinity of x^n/n! < sum from n=i to infinity of 1/n!

    That last sum can be bounded nicely since

    sum from n=0 to infinity of 1/n! = e^1 = e = sum from n=0 to i-1 of 1/n! + sum from n=i to infinity of 1/n!

    which implies

    sum from n=i to infinity of 1/n! = e - sum from n=0 to i-1 of 1/n!

    Put together, we have this error term when |x| < 1:

    e^x - Pi < e - sum from n=0 to i-1 of 1/n!


    I know this doesn't give you the N you wanted, but it does the job--presuming you can compute e to whatever precision you desire. You could loop through computing the partial sum, and each iteration you could update the error term until it's close enough. There are more complicated improvements you could make for very small x, where the error term would be greatly overestimated. Yeah you could use a geometric series to bound it in those cases decently well. Combined the algorithm I'm imagining would do very well; log(x)*[order of squaring and multiplication algorithm] time for the integer part and in the long run well over a digit per iteration for the fractional part of x.
    Last edited by jemidiah; Jul 23rd, 2009 at 06:23 PM.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  3. #3

    Thread Starter
    Addicted Member Latin4567's Avatar
    Join Date
    Jan 2005
    Posts
    202

    Re: Exp series error term help (probably easy for people who know calc)

    Thanks, that should work great -- I actually have a table lookup setup for e and pi with 2 million digits of e and pi built in (LOL). Basically I have an e(digits) function, and whenever a specific value of digits is called, it creates a cache of the BigDecimal variable containing e to that amount of digits instead of substringing the stored e to 2 million digits variable every time. It runs very fast... when I time it there is no detectable difference between using it and using a const



    While I still might attempt getting this series to work, I noticed something on wikipedia that I think might point me in a faster direction... on the page for exponentiation, it briefly mentions that "Rational number exponents can be defined in terms of nth roots, and arbitrary nonzero exponents can then be defined by continuity," but it doesn't elaborate. My nth root function is very fast because it uses newton's method, so I would be very interested in defining exponentiation with rational powers. Any idea how this would be done?

    thanks for your help, btw

  4. #4
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: Exp series error term help (probably easy for people who know calc)

    That quote is referencing the fact that x^(1/n) = nth root of x. You could use this to find e^x by finding e^r for some rational number r=a/b very close to x by noting e^r = e^(a/b) = (e^(1/b))^a--that's what it means "by continuity". You can find r basically by binary search. Estimating the error would be somewhat difficult. I would imagine you would end up with a very large numerator and denominator for large, irrational x which may or may not be a problem.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  5. #5

    Thread Starter
    Addicted Member Latin4567's Avatar
    Join Date
    Jan 2005
    Posts
    202

    Re: Exp series error term help (probably easy for people who know calc)

    I'm trying to define exponentiation. I only have the ability right now to do nth integer powers of integers or decimals, and exponents with decimal or integer bases and integer powers. I need to define exponentiation where the base and the power can both be decimal. The base and power shown are just two random decimals.

    here it is in mathematical notation:


    So is there a quick change I can make that will make this more computationally efficient (it's pathetic at the moment, unless the decimals are short in which case it takes like 10 ms), or have I reached a dead end? I suspect, if I have reached a dead end, that I will have to look into implementing Egyptian fractions (http://en.wikipedia.org/wiki/Egyptian_fraction)

    Here is my current function:
    vb Code:
    1. Shared Function RationalPower(ByVal base As BigDecimal, ByVal power As BigDecimal) As BigDecimal
    2.         Dim k As BigInteger = 10 ^ New BigInteger((DecimalMag(power) - 1))
    3.         Dim kx As BigInteger = k * power
    4.         'Console.WriteLine(k.ToString)
    5.         'Console.WriteLine(kx.ToString)
    6.  
    7.         Dim h As BigInteger = Gcd(kx, k)
    8.         ' Console.WriteLine(h.ToString)
    9.  
    10.         Dim m As BigInteger = kx / h
    11.         'Console.WriteLine("m = " & m.ToString)
    12.         Dim n As BigInteger = k / h
    13.         ' Console.WriteLine(n.ToString)
    14.         ' Console.WriteLine("nth root(" & base.ToString & " ^ " & m.ToString & ", " & n.ToString & ", " & BigDecimal.GlobalScale.ToString & ")")
    15.  
    16.         Return func_internal.nth_root_itr(base ^ m, n, BigDecimal.GlobalScale)
    17.     End Function

    Here is the nth_root function, which is very fast and isn't the problem (the problem is the moronic parameters I'm sending it):

    vb Code:
    1. Shared Function nth_root_itr(ByVal x As BigDecimal, ByVal n As BigInteger, ByVal prec As Integer) As BigDecimal
    2.         If n = 1 Then
    3.             Return x
    4.         End If
    5.         'calculates x^(1/n)
    6.         'f(x) = x^n - x
    7.         'f'(x) = n*x^(n-1)-1
    8.         'x1 = x0 - f(x0)/f'(x0)
    9.         '(f^n-x)/(n*f^(n-1)-1)
    10.         Dim oldscale As Integer = BigDecimal.GlobalScale
    11.         Dim oldroundingmode As RoundingMode = BigDecimal.GlobalRoundingMode
    12.         Dim oldscalingmode As ScalingMode = BigDecimal.GlobalScalingMode
    13.         BigDecimal.SetGlobalScale(prec, ScalingMode.SCALE_ADAPTIVE)
    14.         BigDecimal.GlobalRoundingMode = RoundingMode.ROUND_HALF_EVEN
    15.         Dim f As BigDecimal
    16.         f = 10 ^ New BigInteger(CType(x, BigInteger).ToString.Length / n - 1)
    17.         Dim squared As BigDecimal
    18.         squared = 0
    19.         Dim oldf As BigDecimal = 0
    20.         Dim oldvalues As New List(Of String)
    21.         Do
    22.             oldf = f
    23.             f = f - (f ^ n - x) / (n * f ^ (n - 1) - 1)
    24.             If oldvalues.Contains(f.ToString) Then
    25.                 Exit Do
    26.             End If
    27.             oldvalues.Add(f.ToString)
    28.             ' Console.WriteLine(f.ToString)
    29.  
    30.             If oldf = f Then
    31.                 Exit Do
    32.             End If
    33.         Loop
    34.         BigDecimal.SetGlobalScale(oldscale, oldscalingmode)
    35.         BigDecimal.GlobalRoundingMode = oldroundingmode
    36.         Return f
    37.     End Function

    Here is the Gcd function, which also shouldn't be posing a problem:
    vb Code:
    1. Shared Function Gcd(ByVal a As BigInteger, ByVal b As BigInteger) As BigInteger
    2.         If b > a Then
    3.             Dim tmp As BigInteger
    4.             tmp = a
    5.             a = b
    6.             b = tmp
    7.         End If
    8.         If b = 0 Then
    9.             Return a
    10.         Else
    11.             If a = 0 Then
    12.                 Return b
    13.             Else
    14.                 'Console.WriteLine("Return Gcd(" & a.ToString & ", " & a.ToString & " Mod " & b.ToString & ")")
    15.                 'Console.ReadLine()
    16.                 Return Gcd(b, a Mod b)
    17.             End If
    18.         End If
    19.     End Function

    here is the DecimalMag function, which, for all intensive purposes, returns the number of numbers after the decimal point:

    vb Code:
    1. Shared Function DecimalMag(ByVal x As BigDecimal) As Integer
    2.         Dim n As Integer = 0
    3.         Do
    4.             x = x * 10
    5.             n = n + 1
    6.             If x = Round(x) Then
    7.                 Exit Do
    8.             End If
    9.         Loop
    10.         Return n
    11.     End Function


    The BigInteger and BigDecimal classes are custom , and act as wrappers for the J# BigInteger and BigDecimal classes. I wrote / am writing custom operators and functions so they integrate nicely into vb. I replaced the slow integer multiplication routine with a routine that let's the super fast karasuba multiplication algorithm kick in only when the numbers are of a high enough magnitude for there to be a performance gain.

    I'll be willing to post the whole library if everything works out when it's done. My goal is to be able to treat BigInteger and BigDecimal exactly the way you would treat normal number types in .NET, and I'm well on the way. Exponentiation with rational powers is the last step -- it will allow me to do the Exp function (I could use the taylor series but that is very slow). I already have a very fast routine for the sin, cos, and tan functions. It's also supposed to be able to do exp, cosh, sinh and tanh, but it fails on higher magnitudes. The only reason sin, cos and tan work great is because I am shifting everything to the first period before I send anything to the function (which didn't write, and thus don't really understand at all).

    Alternatively to fixing my rational power routine, if anyone has any tips that will make this work for exp with larger values, here is the function that I didn't write that I am wrapping:

    vb Code:
    1. Shared Function transcendental(ByVal p As TransType, ByVal n As Long, ByVal x As BigDecimal) As BigDecimal
    2.         Dim k As Long
    3.         Dim r As BigDecimal
    4.         Dim s As BigDecimal
    5.         If p <= 3 Then
    6.             r = -x * x 'trig
    7.         Else
    8.             r = x * x 'hyperbolic
    9.         End If
    10.         s = 4 * n + 2
    11.         k = n
    12.         Do
    13.             k = k - 1
    14.             If k = 0 Then
    15.                 Exit Do
    16.             Else
    17.                 s = 4 * k - 2 + r / s
    18.             End If
    19.         Loop
    20.         Dim pmod As Integer
    21.         pmod = p Mod 4
    22.  
    23.         Select Case pmod
    24.             Case 0
    25.                 Return (s + x) / (s - x) 'exp
    26.             Case 1
    27.                 Return 2 * x * s / (s * s - r) 'sin, sinh
    28.             Case 2
    29.                 Return (s * s + r) / (s * s - r) 'cos, cosh
    30.             Case 3
    31.                 Return 2 * x * s / (s * s + r) 'tan, tanh
    32.             Case Else
    33.                 Return (s + x) / (s - x) 'shound't get called, return exp by default
    34.         End Select
    35.     End Function

    and here is my wrapper for it. I have it cut off at 31 because beyond that it begins to fail. The function didn't come with any pointers about how high of an n value you need for different orders of magnitude, so what you see below is my attempt to get it to work (this works the best from what I've tried, but there is probably a much more specific correlation between n and the magnitude of the inputs):

    vb Code:
    1. Shared Function Exp(ByVal x As BigDecimal) As BigDecimal
    2.         If x > 31 Then
    3.             Return Round(e(BigDecimal.GlobalScale) ^ Round(x))
    4.         Else
    5.             Return func_internal.transcendental(func_internal.TransType.Exp, BigDecimal.GlobalScale * 2, x)
    6.         End If
    7.     End Function

    anyway thanks to anyone who can help lead me to properly defining exponentiation with decimal powers!

    FYI: I just graduated from high school, and I have only taken pre-cal. While I can figure a lot of stuff out myself (I got newton's method to work for nth powers using only the wikipedia page on newton's method and mathematica's built in derivative calculator), assume that I will require extra explanation to understand anything beyond pre-calculus


    by the way, as an interesting curiosity, I believe I have developed an extremely efficient factorial algorithm. You can even do it on paper for small-ish values of n with relative ease... it's based on the principal of keeping the magnitude of all multiplications as small as possible for as long as possible. Most of the magnitude gets saved for the last 3-4 multiplications.

    it's easier to demonstrate visually than to explain... here is the process for calculating 10!

    start with a list of 1 through 10:
    1 2 3 4 5 6 7 8 9 10
    instead of multiplying through stupidly, combine the first term with the last, second with second to last, third with third to last, etc,
    10 18 24 28 30
    Since there are an odd number of items, add one to the beginning
    1 10 18 24 28 30
    now repeat the previous steps again and again until you are left with 1 number

    so in the end it looks like this:
    1 2 3 4 5 6 7 8 9 10
    1 10 18 24 28 30
    1 30 280 432
    432 8400
    3628800


    Which is extremely efficient compared to the naive routine, which would look like this

    1
    2
    6
    24
    120
    720
    5040
    40320
    362880
    3628800

    As an example benchmark, my routine calculates 1000!, which has 2568 digits, in 35 milliseconds, whereas the traditional method takes 20 or so minutes (even with karasuba multiplication), and Stirling's approximation takes 433 ms. Of course, it's possible my implementation of Stirling's approximation is horribly inefficient. Suprisingly, my routine is more efficient, even though it involves system.List(Of BigInteger)'s with thousands of items. I'll provide the function if/when I finish / release my library. I'll probably post it on codeplex or something (of course I'll have to eliminate / get permission for some of the code that I didn't write, but most of it I did write)

  6. #6
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: Exp series error term help (probably easy for people who know calc)

    I would have to think through that transcendental routine for a long time to figure it out without any comments. At first glance it looks like some iterative approximation method. I don't think it would be worth the time, though; if it fails at higher magnitudes it's probably only meant to do a good approximation near zero.

    How are you doing integer exponents? That is, how is the "base ^ m" call computed? Exponentiation by squaring has fantastic performance gains for gigantic numbers, perhaps you could try that. Since you're also taking f^n and similar in the nth root routine, a faster exponentiation algorithm might be the thing you need.

    If that ends up not working you could try my original idea, which I'll flesh out slightly more:

    Compute x^y for x and y decimals as follows. Let y = int(y) + frac(y). Compute x^int(y) through exponentiation by squaring. Compute x^frac(y) through the Taylor series, which converges very quickly for y near zero--the only somewhat slow case is for frac(y) ~= 1, though even that should converge quite quickly since the factorial would "take off" after a few iterations. Multiply your numbers to get x^int(y) * x^frac(y) = x^(int(y) + frac(y)) = x^y. Done.


    Also, I liked that factorial computation. I'm surprised the performance gains are as large as you've gotten but I suppose that's the magic of orders of algorithm complexity.
    Last edited by jemidiah; Jul 24th, 2009 at 06:08 PM.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  7. #7

    Thread Starter
    Addicted Member Latin4567's Avatar
    Join Date
    Jan 2005
    Posts
    202

    Re: Exp series error term help (probably easy for people who know calc)

    ah, yes this would explain why my *ahem* implementation of normal exponentiation is slow.... I'm literally multiplying by the base n times.....

    I'll take a look at that article!


    edit: wow that's a major improvement. I feel like such an idiot now. This is also definitely the reason why my Stirling approximation was so slow
    Last edited by Latin4567; Jul 25th, 2009 at 01:59 PM.

  8. #8

    Thread Starter
    Addicted Member Latin4567's Avatar
    Join Date
    Jan 2005
    Posts
    202

    Re: Exp series error term help (probably easy for people who know calc)

    my brain hurts trying to think how I would express my factorial algorithm in mathematical notation

  9. #9

    Thread Starter
    Addicted Member Latin4567's Avatar
    Join Date
    Jan 2005
    Posts
    202

    Re: Exp series error term help (probably easy for people who know calc)

    ok now everything is fast but my log routine (which was horribly inefficent and can't really be salvaged) is slowing everything down. I'm about to begin the search for a more efficient algorithm, but any suggestions on what would be the fastest? I'd imagine log2 would be fastest to compute, and once I have that I have all bases

  10. #10
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: Exp series error term help (probably easy for people who know calc)

    Notation for your factorial algorithm would be a little cumbersome to write up. You'd need two indicies, one tracking which level you're at and one tracking which number in that level. But, the recursive definition from there isn't that bad.

    Either log2 or ln would probably be best to implement, depending on the algorithm you find. There's of course a Taylor series for them, and the one for ln happens to work out nicely. As for algorithms, I don't actually know. I can imagine my own algorithm where I would repeatedly divide by 2, 2^(1/2), 2^(1/4), ... and get the logarithm that way but it wouldn't be efficient for incredibly small numbers. If you wanted 1000 binary bits of precision you'd need to evaluate 2^(1/2^1000). I'm sure you can find something better than that online, though.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width