How to compute the nth root of a very big integer

后端 未结 10 567
暖寄归人
暖寄归人 2020-12-01 06:28

I need a way to compute the nth root of a long integer in Python.

I tried pow(m, 1.0/n), but it doesn\'t work:

OverflowError: lo

相关标签:
10条回答
  • 2020-12-01 06:50

    Well, if you're not particularly worried about precision, you could convert it to a sting, chop off some digits, use the exponent function, and then multiply the result by the root of how much you chopped off.

    E.g. 32123 is about equal to 32 * 1000, the cubic root is about equak to cubic root of 32 * cubic root of 1000. The latter can be calculated by dividing the number of 0s by 3.

    This avoids the need for the use of extension modules.

    0 讨论(0)
  • 2020-12-01 06:53

    Possibly for your curiosity:

    http://en.wikipedia.org/wiki/Hensel_Lifting

    This could be the technique that Maple would use to actually find the nth root of large numbers.

    Pose the fact that x^n - 11968003.... = 0 mod p, and go from there...

    0 讨论(0)
  • 2020-12-01 06:54

    In older versions of Python, 1/3 is equal to 0. In Python 3.0, 1/3 is equal to 0.33333333333 (and 1//3 is equal to 0).

    So, either change your code to use 1/3.0 or switch to Python 3.0 .

    0 讨论(0)
  • 2020-12-01 07:00

    Oh, for numbers that big, you would use the decimal module.

    ns: your number as a string

    ns = "11968003966030964356885611480383408833172346450467339251196093144141045683463085291115677488411620264826942334897996389485046262847265769280883237649461122479734279424416861834396522819159219215308460065265520143082728303864638821979329804885526557893649662037092457130509980883789368448042961108430809620626059287437887495827369474189818588006905358793385574832590121472680866521970802708379837148646191567765584039175249171110593159305029014037881475265618958103073425958633163441030267478942720703134493880117805010891574606323700178176718412858948243785754898788359757528163558061136758276299059029113119763557411729353915848889261125855717014320045292143759177464380434854573300054940683350937992500211758727939459249163046465047204851616590276724564411037216844005877918224201569391107769029955591465502737961776799311859881060956465198859727495735498887960494256488224613682478900505821893815926193600121890632"
    from decimal import Decimal
    d = Decimal(ns)
    one_third = Decimal("0.3333333333333333")
    print d ** one_third
    

    and the answer is: 2.287391878618402702753613056E+305

    TZ pointed out that this isn't accurate... and he's right. Here's my test.

    from decimal import Decimal
    
    def nth_root(num_decimal, n_integer):
        exponent = Decimal("1.0") / Decimal(n_integer)
        return num_decimal ** exponent
    
    def test():
        ns = "11968003966030964356885611480383408833172346450467339251196093144141045683463085291115677488411620264826942334897996389485046262847265769280883237649461122479734279424416861834396522819159219215308460065265520143082728303864638821979329804885526557893649662037092457130509980883789368448042961108430809620626059287437887495827369474189818588006905358793385574832590121472680866521970802708379837148646191567765584039175249171110593159305029014037881475265618958103073425958633163441030267478942720703134493880117805010891574606323700178176718412858948243785754898788359757528163558061136758276299059029113119763557411729353915848889261125855717014320045292143759177464380434854573300054940683350937992500211758727939459249163046465047204851616590276724564411037216844005877918224201569391107769029955591465502737961776799311859881060956465198859727495735498887960494256488224613682478900505821893815926193600121890632"
        nd = Decimal(ns)
        cube_root = nth_root(nd, 3)
        print (cube_root ** Decimal("3.0")) - nd
    
    if __name__ == "__main__":
        test()
    

    It's off by about 10**891

    0 讨论(0)
  • 2020-12-01 07:00

    I came up with my own answer, which takes @Mahmoud Kassem's idea, simplifies the code, and makes it more reusable:

    def cube_root(x):
        return decimal.Decimal(x) ** (decimal.Decimal(1) / decimal.Decimal(3))
    

    I tested it in Python 3.5.1 and Python 2.7.8, and it seemed to work fine.

    The result will have as many digits as specified by the decimal context the function is run in, which by default is 28 decimal places. According to the documentation for the power function in the decimal module, "The result is well-defined but only “almost always correctly-rounded”.". If you need a more accurate result, it can be done as follows:

    with decimal.localcontext() as context:
        context.prec = 50
        print(cube_root(42))
    
    0 讨论(0)
  • 2020-12-01 07:02

    If you are looking for something standard, fast to write with high precision. I would use decimal and adjust the precision (getcontext().prec) to at least the length of x.

    Code (Python 3.0)

    from decimal import *
    
    x =   '11968003966030964356885611480383408833172346450467339251\
    196093144141045683463085291115677488411620264826942334897996389\
    485046262847265769280883237649461122479734279424416861834396522\
    819159219215308460065265520143082728303864638821979329804885526\
    557893649662037092457130509980883789368448042961108430809620626\
    059287437887495827369474189818588006905358793385574832590121472\
    680866521970802708379837148646191567765584039175249171110593159\
    305029014037881475265618958103073425958633163441030267478942720\
    703134493880117805010891574606323700178176718412858948243785754\
    898788359757528163558061136758276299059029113119763557411729353\
    915848889261125855717014320045292143759177464380434854573300054\
    940683350937992500211758727939459249163046465047204851616590276\
    724564411037216844005877918224201569391107769029955591465502737\
    961776799311859881060956465198859727495735498887960494256488224\
    613682478900505821893815926193600121890632'
    
    minprec = 27
    if len(x) > minprec: getcontext().prec = len(x)
    else:                getcontext().prec = minprec
    
    x = Decimal(x)
    power = Decimal(1)/Decimal(3)
    
    answer = x**power
    ranswer = answer.quantize(Decimal('1.'), rounding=ROUND_UP)
    
    diff = x - ranswer**Decimal(3)
    if diff == Decimal(0):
        print("x is the cubic number of", ranswer)
    else:
        print("x has a cubic root of ", answer)
    

    Answer

    x is the cubic number of 22873918786185635329056863961725521583023133411 451452349318109627653540670761962215971994403670045614485973722724603798 107719978813658857014190047742680490088532895666963698551709978502745901 704433723567548799463129652706705873694274209728785041817619032774248488 2965377218610139128882473918261696612098418

    0 讨论(0)
提交回复
热议问题