pyzuki

Series_L_Upper_Lower_Bounds.py

Sep 13th, 2011
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.27 KB | None | 0 0
  1. # series_L_Upper_Lower_Bounds22b.py --> Series_L_Upper_Lower_Bounds.py
  2.  
  3. # try to set up an option to set that shows a new result only when there is a new idx
  4. # Did that.
  5. # Also set up an easy way to configure to compute for only a single n
  6. #
  7. #===========================================
  8.  
  9. # "The Euler Series" on p.31 in "The Pleasures of Pi,e" is
  10.  
  11. # 1/1**2 + 1/2**2 + 2/3**2 + ... + 1/n**2 + ... --> pi**2/6  
  12.  
  13. # The partial sums converge very slowly to pi**2/6, so I use Hans Lundmark's post on http://math.stackexchange.com, at
  14. # http://math.stackexchange.com/questions/8337/different-methods-to-compute-sum-n-1-infty-frac1n2
  15.  
  16. # There's an image of the last inequality in his proof at http://www.rcblue.com/images/PinchingForEuler.jpg
  17.  
  18. # I use this inequality after multiplying the 3 expressions by (math.pi**2/(4**(n+1)))
  19. # Thus upper_bound_partial_sum = (2*(4**n - 1)/3) * (math.pi**2/(4**(n+1)))
  20. # and lower_bound_partial_sum = (2*(4**n - 1)/3 - (2**n - 1)) * (math.pi**2/(4**(n+1)))
  21.  
  22. # The middle expression becomes lines 49-56 below,
  23. # which compute the euler_series_partial_sum for a given n
  24.  
  25. # NOTE: the above 2 lines are no longer true. The middle term takes so long to compute that
  26. # the demo is not very intersting. So I decided to just show that the upper and lower bounds on the Euler
  27. # Series partial sums get VERY close to one another, and in fact are identical
  28. # for a large number of their initial digits.
  29.  
  30. #For singleton_first_n = 10,000,000 the output is
  31. # (for singleton_first_n, see main() )
  32.  
  33. #=================================================
  34. #1.6449340668482264364724151666...351904003992141795698445313293*7211734124
  35. #For n = 10,000,000  idx = 3,010,301
  36. #the first 3,010,300 digits of upper and lower match up to the asterisk
  37. #That's 4.8e+00 miles at 10 digits/inch.
  38. #1.6449340668482264364724151666...351904003992141795698445313293*4485269029
  39.  
  40. #time was 23.4294 seconds  or  00:00:23.43
  41. #=====================================================
  42.  
  43. # Thus this script demos the "pinching down" (for increasing values of n)
  44. # on the middle expression's value by the upper_bound_partial_sum from above,
  45. # and the lower_bound_partial_sum from below.
  46. # Because the limits of both the upper_bound_partial_sum's and the lower_bound_partial_sum's are pi^2/6,
  47. # the limit of the euler_series_partial_sum's must also be pi^2/6. Q.E.D.
  48.  
  49. from mpmath import *; mp.pretty = True  # mp.dps is set in main() for each n
  50.  
  51. from time import clock
  52. import sys
  53.  
  54. def tim(t, digits, p=1):
  55.     time_  = clock() - t
  56.     if digits:
  57.         seconds = round(time_, digits)
  58.         minutes = round(time_/60, digits)
  59.         hours = round(time_/3600, digits)
  60.     else:
  61.         seconds = int(round(time_, digits))
  62.         minutes = int(round(time_/60, digits))
  63.         hours = int(round(time_/3600, digits))
  64.     if p and seconds > 3600:
  65.         print("time was", hours, "hours  or ", secsToHMS(time_))
  66.     elif p and seconds > 60:
  67.         print("time was", minutes, "minutes  or ", secsToHMS(time_))
  68.     elif p:
  69.         print("time was", seconds, "seconds  or ", secsToHMS(time_))
  70.     else:
  71.         return secsToHMS(time_)
  72.    
  73. def secsToHMS(seconds):
  74.     """
  75.    Convert seconds to hours:minutes:seconds, with seconds rounded to hundredths of a second.
  76.    """
  77.     minutes, seconds = divmod(seconds, 60)
  78.     hours, minutes = divmod(minutes, 60)
  79.     return "%02d:%02d:%05.2f" % (hours, minutes, seconds)
  80.  
  81.  
  82. def int_commas(n):
  83.     """
  84.    inserts commas into integers and returns the string
  85.  
  86.    E.g. -12345678 -> -12,345,789
  87.    """
  88.     return format(n, ',d')
  89.  
  90. def compareSequences(seq1, seq2):
  91.     """
  92.    Returns first index at which two sequences differ. If one is longer than the other,
  93.    ignores the elements of the longer for which there are no corresponding elements in the shorter.
  94.    """
  95.     if len(seq2) > len(seq1):
  96.         seq1, seq2 = seq2, seq1
  97.     for index in range(0, len(seq2)):
  98.         if seq1[index] != seq2[index]:
  99.             return index
  100.        
  101. def num_digits2int_length(num_digits, dpi = 10):
  102.     """
  103.    Given number of digits of (large) integer n,
  104.    returns length of n in miles
  105.  
  106.    For my laptop monitor, there are
  107.    about 10 digits per inch (dpi = 10)
  108.    """
  109.     #digits = int_digits(n)
  110.     miles = num_digits/dpi/12/5280
  111.     return miles
  112.  
  113. def sig_digits(n, d=6):
  114.     """
  115.    Return any real number n to d significant digits, in scientific notation.
  116.    """
  117.     return '%.*e' % (d-1, n)
  118.  
  119. def demo(n, complete, first_n, idx, prev_idx):
  120.     n = mpf(n)
  121.     prev_idx = idx
  122.     upper_bound_partial_sum = (2*(4**n - 1)/3) * (pi()**2/(4**(n+1)))
  123.     lower_bound_partial_sum = (2*(4**n - 1)/3 - (2**n - 1)) * (pi()**2/(4**(n+1)))
  124.    
  125.     idx = compareSequences(str(upper_bound_partial_sum), str(lower_bound_partial_sum))
  126.    
  127.     if n > first_n and idx != prev_idx:
  128.         if n < 384 or complete == True:
  129.             #if complete == True:
  130.             upper = str(upper_bound_partial_sum)[:idx] + '*' + str(upper_bound_partial_sum)[idx:idx+10]
  131.             lower = str(lower_bound_partial_sum)[:idx] + '*' + str(lower_bound_partial_sum)[idx:idx+10]
  132.             print(upper)
  133.             print("for n =", int_commas(int(n)), " idx =", int_commas(idx))
  134.             print("the first", idx-1, "digits of upper and lower match up to the asterisk")
  135.             print("for n =", int_commas(int(n)), " idx =", int_commas(idx))
  136.             print(lower)
  137.            
  138.         else:
  139.             upper1 = str(upper_bound_partial_sum)[:30]
  140.             upper2 = str(upper_bound_partial_sum)[idx-30:idx] + '*' + str(upper_bound_partial_sum)[idx:idx+10]
  141.             upper = upper1 + '...' + upper2
  142.             lower = str(lower_bound_partial_sum)[idx-50:idx] + '*' + str(lower_bound_partial_sum)[idx:idx+10]
  143.             print(upper)
  144.             print("For n =", int_commas(int(n)), " idx =", int_commas(idx))
  145.             print("the first", int_commas(idx-1), "digits of upper and lower match up to the asterisk")
  146.             print("That's", sig_digits(num_digits2int_length(idx-1),2), "miles at 10 digits/inch.")
  147.             lower1 = str(lower_bound_partial_sum)[:30]
  148.             lower2 = str(lower_bound_partial_sum)[idx-30:idx] + '*' + str(lower_bound_partial_sum)[idx:idx+10]
  149.             lower = lower1 + '...' + lower2
  150.             print(lower)
  151.         print()
  152.     return idx
  153.  
  154.    
  155. def main():
  156.     t0 = clock()
  157.     singleton = 1
  158.     singleton_first_n = 10000000
  159.     if singleton_first_n > 646456000:
  160.         print("DAME!! n must be <= 646456000")
  161.         print("Exiting.")
  162.         sys.exit()
  163.    
  164.     first_n = 564
  165.     last_n = 574
  166.     every_nth = 1
  167.     if singleton:
  168.         first_n = singleton_first_n
  169.         last_n = first_n
  170.         first_n -= 1
  171.         every_nth = 1
  172.     else:
  173.         first_n -= every_nth
  174.        
  175.     complete = 0
  176.     idx = 0
  177.     prev_idx = 0
  178.     for n in range(first_n, last_n+1, every_nth):
  179.         #this should ensure that n+1 will not be skipped
  180.         if n == first_n:
  181.             n = -20
  182.             prev_idx = 0
  183.         #make mp.dps large enough (but not too large) for small n
  184.         if n < 150:
  185.             mp.dps = 65
  186.         else:
  187.             #get mp.dps just about right for larger n
  188.             mp.dps = int(n/2.5)
  189.         #until this point n shouldn't be an mpf (for n = -20, and assigning mp.dpf)
  190.         n = mpf(n)
  191.         idx = demo(n, complete, first_n, idx, prev_idx)
  192.        
  193.     if n >= 1000000:
  194.         tim(t0, 4)
  195.        
  196. if __name__ == '__main__':
  197.     main()
  198.  
  199. """
  200. OUTPUT
  201. C:\P32Working\Series>series_L_Upper_Lower_Bounds22a.py
  202. 80209552093784631871255223825845694405451612628725*4702464901
  203. for n = 646,456,000  idx = 194,602,648
  204. That's 3.1e+02 miles at 10 digits/inch.
  205. the first 194602647 digits of upper and lower match up to the asterisk (307 miles at 10 digits/inch)
  206. 80209552093784631871255223825845694405451612628725*1426908163
  207.  
  208. time was 47.9024 minutes  or  00:47:54.14
  209. ===========================================
  210. 79692796739533168682606523239647663116122558403219*7481745350
  211. For n = 100,000,000  idx = 30,103,000
  212. the first 30,102,999 digits of upper and lower match up to the asterisk
  213. That's 4.8e+01 miles at 10 digits/inch.
  214. 79692796739533168682606523239647663116122558403219*6812104970
  215.  
  216. time was 5.256 minutes  or  00:05:15.36
  217.  
  218.  
  219. """
Advertisement
Add Comment
Please, Sign In to add comment