【问题标题】:Converting An "Infinite" Float To An Int [duplicate]将“无限”浮点数转换为 Int [重复]
【发布时间】:2014-05-09 04:09:23
【问题描述】:

我正在尝试检查一个数字是否是一个完美的正方形。但是,我正在处理非常大的数字,所以 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")

【问题讨论】:

    标签: python int type-conversion infinite infinity


    【解决方案1】:

    我认为你需要看看BigFloat 模块,例如:

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

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

    【讨论】:

    • 在不提高精度的情况下,不测试是否是完美正方形。
    • 为什么使用这个模块而不是Decimal
    【解决方案2】:

    math.sqrt() 将参数转换为 Python 浮点数,最大值约为 10^308。

    您可能应该考虑使用gmpy2 库。 gmpy2 提供了非常快速的多精度算法。

    如果您想检查任意幂,函数gmpy2.is_power() 将返回True,如果数字是完美幂。它可能是立方或五次方,因此您需要检查您感兴趣的功率。

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

    您可以使用gmpy2.isqrt_rem() 来检查它是否是一个精确的正方形。

    >>> gmpy2.isqrt_rem(9)
    (mpz(3), mpz(0))
    >>> gmpy2.isqrt_rem(10)
    (mpz(3), mpz(1))
    

    您可以使用gmpy2.iroot_rem() 来检查任意权力。

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

    【讨论】:

    • 有理由不首先使用 isqrt_rem() 吗? is_power() 是否明显更快?
    • @RoryYorke 我刚刚再次为这两个函数计时。 isqrt_rem() 比 is_power() 快。 is_power() 具有检查所有可能的权力的优势。我会更新答案。
    • @RoryYorke 我在计时测试中做了一个类型。 is_power() 明显快于 isqrt_rem()。
    【解决方案3】:

    math.sqrt(Decimal(i)) 替换为Decimal(i).sqrt() 以防止您的Decimals 衰减为floats

    【讨论】:

      【解决方案4】:

      @casevh 有正确的答案——使用可以对任意大整数进行数学运算的库。由于您正在寻找平方,因此您可能正在使用整数,并且有人可能会争辩说使用浮点类型(包括 decimal.Decimal)在某种意义上是不雅的。

      你绝对不应该使用 Python 的 float 类型;它的精度有限(大约小数点后 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)
      

      【讨论】:

        猜你喜欢
        • 2023-03-11
        • 1970-01-01
        • 2014-09-03
        • 1970-01-01
        • 2022-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-05
        相关资源
        最近更新 更多