pythonpython-3.xdigitsexponentoverflowexception

How to calculate and write a very, very large number to a file in python?


This may seem like a duplicate question, and maybe it is, but I've checked many other sources and none of the solutions seem to work. The number I'm trying to calculate is 999,999^999,999, and it's pointlessly large, but I've been trying to get it for a while now. I want to write the result to a text file. I usually get Overflow errors, and after trying a solution for another question, I started getting different Overflow messages. Is there any way I can calculate this number? If python can't do it, can something else?

My code at this point:

from decimal import Decimal

#Attempt 2 (Attempt 1 was just print(999999**999999))
a = Decimal(999999**999)
a = a**(2) #Not close enough. 2.0002895717 would be perfect, but that would cause another Overflow: "OverflowError: int too large to convert to float"
print(a)
open("number.txt","x").write(str(a))

#Attempt 3, I tried breaking down the power into it's square root, and then that into it's square roots
massiveNumber = Decimal(999999**31.6227608)
massiveNumber = Decimal(massiveNumber**Decimal(31.6227608))
massiveNumber = Decimal(massiveNumber**Decimal(31.6227608))
massiveNumber = Decimal(massiveNumber**Decimal(31.6227608))

open("number.txt","w").write(str(massiveNumber))

The error:

Traceback (most recent call last):
  File "unknowablenumber.py", line 13, in <module>
    massiveNumber = Decimal(massiveNumber**Decimal(31.6227608))
decimal.Overflow: [<class 'decimal.Overflow'>]

Solution

  • Yes, decimal can do it exactly, and quickly, but you need to boost the internal precision it uses:

    import decimal
    with decimal.localcontext() as ctx:
        ctx.prec = decimal.MAX_PREC
        ctx.Emax = decimal.MAX_EMAX
        ctx.Emin = decimal.MIN_EMIN
    
        n = decimal.Decimal(999999)
        huge = n ** n
        s = str(huge)
        print(len(s))
        print (s[:10], "...", s[-10:])
    

    That displays:

    5999994
    3678796251 ... 9998999999
    

    As a sanity check,

    >>> import math
    >>> math.log10(999999) * 999999
    5999993.565705735
    >>> 10 ** .565705735
    3.67879624904532
    >>> pow(999999, 999999, 10**10)
    9998999999
    

    so the result from decimal has the right number of digits, the leading digits match, and the last 10 digits are exactly right.