5

I just come up to one of challenges that claimed to be used by google 2004

(the first 10-digit prime in e).com 

independent from that, I wanted to take the challenge and solve it with python

>>> '%0.52f' % math.exp(1)
'2.71828182845904509079**5598298427**6488423347473144531250'
>>> '%0.52f' % numpy.exp(1)
'2.71828182845904509079**5598298427**6488423347473144531250'

my program returned 5598298427 which is a prime number

after looking on the internet the right answer was7427466391

but the exp number in python doesn't include that digits as you can see above

import numpy
import math

def prime(a):
    if a == 2: return True
    if a % 2 == 0: return False
    if a < 2: return False
    i = 2
    n = math.sqrt(a) + 1
    while(i < n):
        if a % i == 0:
            return False
        i += 1
    return True

def prime_e():
    e = '%0.51f' % math.exp(1)
    e = e.replace("2.","")
    for i in range(len(e)):
        x = int(e[i:10+i])
        if prime(x):
            return [i, x]

print prime_e()

so am I doing something wrong ?


EDIT: using gmpy2

def exp():
    with gmpy2.local_context(gmpy2.context(), precision=100) as ctx:
        ctx.precision += 1000
        return gmpy2.exp(1)

returns 7427466391 after 99 iterations

Elteroooo
  • 2,913
  • 3
  • 33
  • 40
  • 1
    You could also use the standard library `decimal` module: for example `decimal.getcontext().prec = 1000; e = decimal.Decimal(1).exp()`. – Mark Dickinson Sep 02 '15 at 17:23
  • Thanks a lot, while searching on internet about precision, i came only to `bigfloat` and `gmpy2`. I faced problems compiling the both on windows, but gmpy2 had already a compiled version for windows – Elteroooo Sep 03 '15 at 08:26
  • 1
    Yes, my bad: I've never had the time or resources for packaging `bigfloat` properly for Windows. Out of those two, `gmpy2` is definitely the right choice. – Mark Dickinson Sep 03 '15 at 08:29

4 Answers4

3

Actual e (Euler constant) value is

http://www.gutenberg.org/files/127/127.txt

2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059921817413596629043572900334295260595630...

and so the right answer for the challenge is 7427466391. You can't compute e with requiered precision by math.exp(1)

dan04
  • 87,747
  • 23
  • 163
  • 198
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • 2
    To expand on this, an IEEE double is only precise to 53 binary digits, which is 15 or 16 decimal digits. The result of `math.exp(1)` is a 53-binary-digit number that's within 1 digit of e at the 53rd binary digit. Beyond that position it bears no relation to e, although Python will still give you the exact decimal representation of it out to 53 decimal places. – Steve Jessop Sep 02 '15 at 13:03
  • 1
    @ElTero: As for *prime testing* for this *exact problem* it is. However, *one (1)* is *not* a prime number however your routine say it is; another doubtful thing is `i += 1`: you can check not every potential divider (`2, 3, 4, 5...`) but `odd` ones (`3, 5, 7..`) – Dmitry Bychenko Sep 02 '15 at 13:14
  • @DmitryBychenko you are right, but for 1 i just copied the above line: `if a < 2 == 0: return False` -> `if a < 2: return False` forgot to delete `== 0`. – Elteroooo Sep 02 '15 at 13:20
1

Here is a way to do it:

Generate 1st 1000 digits of e using continued fractions method with answer by @quantum in Code to Generate e one Digit at a Time, which is from answer by @wnoise in Generating digits of square root of 2, which is an "adaptation of Haskell code ... that has been floating around":

def z(contfrac, a=1, b=0, c=0, d=1):
    for x in contfrac:
        while a > 0 and b > 0 and c > 0 and d > 0:
            t = a // c
            t2 = b // d
            if not t == t2:
                break
            yield t
            a = (10 * (a - c*t))
            b = (10 * (b - d*t))
            # continue with same fraction, don't pull new x
        a, b = x*a+b, a
        c, d = x*c+d, c
    for digit in rdigits(a, c):
        yield digit

def rdigits(p, q):
    while p > 0:
        if p > q:
           d = p // q
           p = p - q * d
        else:
           d = (10 * p) // q
           p = 10 * p - q * d
        yield d    

def e_cf_expansion():
    yield 1
    k = 0
    while True:
        yield k
        k += 2
        yield 1
        yield 1

def e_dec():
    return z(e_cf_expansion())

gen = e_dec()
e = [str(gen.next()) for i in xrange(1000)]
e.insert(1, '.')

Function to test primality of an integer selected for efficiency from Rosetta Code Primality_by_trial_division#Python:

def isprime(a):
    if a < 2: return False
    if a == 2 or a == 3: return True # manually test 2 and 3   
    if a % 2 == 0 or a % 3 == 0: return False # exclude multiples of 2 and 3
    maxDivisor = a**0.5
    d, i = 5, 2
    while d <= maxDivisor:
        if a % d == 0: return False
        d += i 
        i = 6 - i # this modifies 2 into 4 and viceversa
    return True

Find the first 10 digit prime in e (my contribution):

for i in range(len(e[2:])-10):
  x = int(reduce(operator.add,e[2:][i:i+10]))
  if isprime(x):
      print x
      print i
      break

This prints:

7427466391
98

Meaning that the first 10 digit prime in e occurs in the 98th postion after the decimal point in agreement with http://explorepdx.com/firsten.html under 'The location of the answer'.

A simpler way to generate digits of e is with Euler's series expansion which can be done as follows with code adapted from Euler's Number with 100 Digit Precision (Python) that uses Python's Decimal class for adequate precision:

import operator
import decimal as dc

def edigits(p):
    dc.getcontext().prec = p
    factorial = 1
    euler = 2
    for x in range(2, 150):
        factorial *= x
        euler += dc.Decimal(str(1.0))/dc.Decimal(str(factorial))
    return euler

estring = edigits(150).to_eng_string()[2:]

for i in range(len(estring)-10):
    x = int(reduce(operator.add,estring[i:i+10]))
    if isprime(x):
        print x
        print i
        break

This prints:

7427466391
98   

As pointed out by @MarkDickinson an even easier method is to use the decimal module directly to generate e with the necessary precision. For example:

import operator
import decimal

decimal.getcontext().prec = 150
e_from_decimal = decimal.Decimal(1).exp().to_eng_string()[2:]
for i in range(len(e_from_decimal)-10):
    x = int(reduce(operator.add,e_from_decimal[i:i+10]))
    if isprime(x):
        print x
        print i
        break  

This prints:

7427466391
98
Community
  • 1
  • 1
  • 1
    If you're going to import the decimal module, you might as well just do `decimal.Decimal(1).exp()`, with suitable precision. – Mark Dickinson Sep 02 '15 at 17:20
  • @MarkDickinson: thanks. I upvoted your comment and added direct use of the decimal module to generate e with sufficient precision to my answer crediting you. –  Sep 02 '15 at 17:59
  • 1
    Thanks! I confess to being biased: I was responsible for implementing the `Decimal.exp` method (at least in Python 2, before the conversion of the decimal module to C), so it's nice to see it get used occasionally. (Even if it is *very* occasionally :-) – Mark Dickinson Sep 02 '15 at 18:03
  • I don't understand what this does `reduce(operator.add`. I checked your code without it and still works `int(euler_number[i:i+10])` – Claudiu Creanga Dec 30 '15 at 20:15
0

The problem is that your 'e' is wrong after the 15th decimal (09079 and onwards) for reasons that others have explained here. However, python itself has all the tools onboard to provide 'e' with virtually unlimited precision. I haven't come across this solution yet, so I decided to post it here. The magic is in the 'long' int, which can be as long as the memory of your machine permits. Since a float is nothing more than an int divided by some power of 10, we can easily calculate (and store) e_as_int=e*10**d, where d is the number of required decimals. The simple code below generates e from the series for the natural logarithm:

import itertools
count = itertools.count

def ape(digits):
    # e = sum(1/k! for k in count())
    # calculate some extra digits to compensate for loss of precision:
    r = 3    
    m = 10**(digits+r)
    e = 2*m
    f = 1   #initial value for k!
    for k in count(2):
        f *= k
        if f>m: break
        # remember, we're doing int division, so m/f = 0 for f>m
        e += (m/f)

    return e/10**r #truncate to required precision

'ape' stands for 'approximation of e' and reflects the simplicity of it quite well:-) This algo finds 10000 digits of e in about a second on my machine.

Hermen
  • 111
  • 4
0

You know I appreciate everyone making theres super efficient and complicated, but if you want the poor mans solution to the problem (ie. lamen terms) here V

def is_Prime(num):
    for i in range(2, num):
        if num % i == 0:
            return False
    return True

e = '2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174'

value = 4
left = 1
while is_Prime(value) == False:
    left += 1
    value = e[left] + e[left + 1] + e[left + 2] + e[left + 3] + e[left + 4] + e[left + 5] + e[left + 6] + e[left + 7] + e[left + 8] + e[left + 9]
    value = int(value)
    print(value)