舍入** 0.5和math.sqrt

时间:2013-06-06 18:37:44

标签: python math square-root

在Python中,要么是

n**0.5  # or
math.sqrt(n) 

当一个数字是一个完美的正方形时被认出来?具体来说,当我使用

时,我应该担心吗?
int(n**0.5)  # instead of
int(n**0.5 + 0.000000001)

由于精度错误,我可能不小心最终得到的数字小于实际的平方根?

6 个答案:

答案 0 :(得分:5)

由于有几个答案提出了整数运算,我建议使用gmpy2库。它提供了检查数字是否是完美幂的函数,计算整数平方根和带余数的整数平方根。

>>> import gmpy2
>>> gmpy2.is_power(9)
True
>>> gmpy2.is_power(10)
False
>>> gmpy2.isqrt(10)
mpz(3)
>>> gmpy2.isqrt_rem(10)
(mpz(3), mpz(1))

免责声明:我维持gmpy2。

答案 1 :(得分:4)

是的,你应该担心:

In [11]: int((100000000000000000000000000000000000**2) ** 0.5)
Out[11]: 99999999999999996863366107917975552L

In [12]: int(math.sqrt(100000000000000000000000000000000000**2))
Out[12]: 99999999999999996863366107917975552L

显然添加0.000000001在这里没有帮助...

正如@DSM指出的那样,您可以使用decimal库:

In [21]: from decimal import Decimal

In [22]: x = Decimal('100000000000000000000000000000000000')

In [23]: (x ** 2).sqrt() == x
Out[23]: True

对于超过10**999999999的数字,如果您检查精度(可配置),它会抛出错误而不是错误的答案......

答案 2 :(得分:3)

**0.5math.sqrt()都使用浮点运算执行计算。在计算平方根之前,输入将转换为浮点数。

  

当输入值是完美的正方形时,这些计算会识别吗?

不,他们没有。浮动算术没有完美正方形的概念。

对于数字具有比浮点尾数中可用的更高有效数字的值,大整数可能无法表示。因此很容易看出,对于不可表示的输入值,n**0.5可能是不准确的。而你建议通过添加一个较小的值来解决这个问题。

如果您的输入是整数,那么您应该考虑使用整数运算来执行计算。这最终是解决这个问题的正确方法。

答案 3 :(得分:1)

你可以在转换为int之前使用round(number,significant_figures),我无法回想起在进行浮点到整数转换时是否有python截断或舍入。

在任何情况下,由于python使用浮点运算,所有陷阱都适用。请参阅:
http://docs.python.org/2/tutorial/floatingpoint.html

答案 4 :(得分:1)

完美平方值将没有小数分量,因此您的主要担心是非常大的值,对于这样的值,1或2的差异是重要的意味着您将需要支持如此高的特定数值库精度(正如DSM所提到的,Decimal库,自Python 2.4以来的标准,应该能够做到你想要的,因为它支持任意精度。

http://docs.python.org/library/decimal.html

答案 5 :(得分:1)

sqrt是要实现的更简单的数学库函数之一,任何质量合理的数学库都会通过忠实的舍入(子ULP精度)来实现它。如果输入是完美的正方形,则其平方根可表示(以合理的浮点格式)。在这种情况下,忠实的舍入保证结果是准确的。

这仅解决实际传递给sqrt的值。数字是否可以在没有错误的情况下从另一种格式转换为sqrt的浮点输入是一个单独的问题。