2014-03-29 167 views
2

我試圖檢查一個數字是否是一個完美的正方形。然而,我正在處理非常大的數字,所以Python出於某種原因認爲它的無窮大。在代碼返回「Inf」之前,它會達到1.1 X 10^154。無論如何要解決這個問題嗎?下面是代碼,地表溫度變化只抱了一堆真的真的真的真的真的大數字的將一個「無限」浮點數轉換爲一個整數

import math 
from decimal import Decimal 
def main(): 
for i in lst: 
    root = math.sqrt(Decimal(i)) 
    print(root) 
    if int(root + 0.5) ** 2 == i: 
     print(str(i) + " True") 

回答

2

我認爲你需要看看在BigFloat模塊,如:

import bigfloat as bf 
b = bf.BigFloat('1e1000', bf.precision(21)) 
print bf.sqrt(b) 

打印BigFloat.exact('9.9999993810013282e+499', precision=53)

+0

不增加精度,它不測試它是否是一個完美的正方形。 – casevh

+1

爲什麼使用這個模塊而不是使用'Decimal'? – delnan

1

math.sqrt()將參數轉換爲具有10^308左右最大值的Python浮點數。

您應該看看使用gmpy2庫。 gmpy2提供了非常快速的多精度算法。

如果你想檢查任意功率,如果一個數字是一個完美的功率,功能gmpy2.is_power()將返回True。它可能是一個立方體或第五威力,您將需要檢查的權力,你有興趣。

>>> gmpy2.is_power(456789**372) 
True 

您可以使用gmpy2.isqrt_rem()來檢查它是否是一個確切的平方。可以使用gmpy2.iroot_rem()來檢查任意的權力。

>>> gmpy2.iroot_rem(13**7 + 1, 7) 
(mpz(13), mpz(1)) 
+0

是否有原因不首先使用isqrt_rem()? is_power()明顯更快嗎? –

+0

@RoryYorke我只是再次計時兩個函數。 isqrt_rem()比is_power()更快。 is_power()具有檢查所有可能的功能的優點。我會更新答案。 – casevh

+0

@RoryYorke我在我的時間測試中做了一個類型。 is_power()比isqrt_rem()快得多。 – casevh

2

更換math.sqrt(Decimal(i))Decimal(i).sqrt(),以防止你的Decimal小號衰變成float小號

1

@casevh有正確的答案 - 使用可以對任意大的整型做數學庫。既然你正在尋找正方形,你可能正在用整數工作,並且有人可能會爭辯說使用浮點類型(包括decimal.Decimal)在某種意義上是不雅觀的。

你肯定不應該使用Python的浮點類型;它的精度有限(約16位小數)。如果你確實使用了decimal.Decimal,注意指定精度(這取決於數字的大小)。

由於Python有一個大整數類型,所以可以編寫一個合理簡單的算法來檢查矩形性;請參閱我的這種算法的實現,以及浮點問題的說明,以及如何使用下面的decimal.Decimal。

import math 
import decimal 

def makendigit(n): 
    """Return an arbitraryish n-digit number""" 
    return sum((j%9+1)*10**i for i,j in enumerate(range(n))) 
x=makendigit(30) 

# it looks like float will work... 
print 'math.sqrt(x*x) - x: %.17g' % (math.sqrt(x*x) - x) 
# ...but actually they won't 
print 'math.sqrt(x*x+1) - x: %.17g' % (math.sqrt(x*x+1) - x) 

# by default Decimal won't be sufficient... 
print 'decimal.Decimal(x*x).sqrt() - x:',decimal.Decimal(x*x).sqrt() - x 
# ...you need to specify the precision 
print 'decimal.Decimal(x*x).sqrt(decimal.Context(prec=30)) - x:',decimal.Decimal(x*x).sqrt(decimal.Context(prec=100)) - x 

def issquare_decimal(y,prec=1000): 
    x=decimal.Decimal(y).sqrt(decimal.Context(prec=prec)) 
    return x==x.to_integral_value() 

print 'issquare_decimal(x*x):',issquare_decimal(x*x) 
print 'issquare_decimal(x*x+1):',issquare_decimal(x*x+1) 

# you can check for "squareness" without going to floating point. 
# one option is a bisection search; this Newton's method approach 
# should be faster. 

# For "industrial use" you should use gmpy2 or some similar "big 
# integer" library. 
def isqrt(y): 
    """Find largest integer <= sqrt(y)""" 
    if not isinstance(y,(int,long)): 
     raise ValueError('arg must be an integer') 
    if y<0: 
     raise ValueError('arg must be positive') 
    if y in (0,1): 
     return y 
    x0=y//2 
    while True: 
     # newton's rule 
     x1= (x0**2+y)//2//x0 
     # we don't always get converge to x0=x1, e.g., for y=3 
     if abs(x1-x0)<=1: 
      # nearly converged; find biggest 
      # integer satisfying our condition 
      x=max(x0,x1) 
      if x**2>y: 
       while x**2>y: 
        x-=1 
      else: 
       while (x+1)**2<=y: 
        x+=1 
      return x 
     x0=x1 

def issquare(y): 
    """Return true if non-negative integer y is a perfect square""" 
    return y==isqrt(y)**2 

print 'isqrt(x*x)-x:',isqrt(x*x)-x 

print 'issquare(x*x):',issquare(x*x) 
print 'issquare(x*x+1):',issquare(x*x+1) 
相關問題