我想在Python3中计算一个非常大的立方根。
我已经尝试了下面的函数以及Python语法x ** (1 / n)
,但是它们都产生错误:
OverflowError: (34, 'Numerical result out of range')
我真的需要计算立方根才能解决密码学中的问题。除了数学,我不能使用任何其他模块。
二元搜索:
def find_invpow(x,n):
"""Finds the integer component of the n'th root of x,
an integer such that y ** n <= x < (y + 1) ** n.
"""
high = 1
while high ** n < x:
high *= 2
low = high/2
while low < high:
mid = (low + high) // 2
if low < mid and mid**n < x:
low = mid
elif high > mid and mid**n > x:
high = mid
else:
return mid
return mid + 1
导致错误的示例数字是:
num = 68057481137876648248241485864416419482650225630788641878663638907856305801266787545152598107424503316701887749720220603415974959561242770647206405075854693761748645436474693912889174270087450524201874301881144063774246565393171209785613106940896565658550145896382997905000280819929717554126192912435958881333015570058980589421883357999956417864406416064784421639624577881872069579492555550080496871742644626220376297153908107132546228975057498201139955163867578898758090850986317974370013630474749530052454762925065538161450906977368449669946613816
结果应该是这样(这是gmpy2所找到的内容,并且它是正确的-我已验证):
408280486712458018941011423246208684000839238529670746836313590220206147266723174123590947072617862777039701335841276608156219318663582175921048087813907313165314488199897222817084206
答案 0 :(得分:3)
您的问题是您不严格遵守整数。 Python的整数是动态大小的,因此它们可以适合您想要的任何大小的值,而不会损失任何精度。但是浮点数固有地具有有限的精度。
当您进行low = high/2
时,即使您不打算进行浮点计算,也可以进行计算。由于low
是一个浮点数,因此mid
也最终成为一个浮点数,并且当您测试mid
的多维数据集时,浮点数最终会溢出并且会出现异常。
如果将low
的第一个计算更改为使用//
而不是/
,则在整个计算过程中将坚持使用整数,并且不会出现溢出异常。只需进行一次更改,我就可以运行您的代码并获得您期望的结果:
>>> find_invpow(num, 3)
408280486712458018941011423246208684000839238529670746836313590220206147266723174123590947072617862777039701335841276608156219318663582175921048087813907313165314488199897222817084206