舍入 ** 0.5 和 math.sqrt

问题描述 投票:0回答:7

在 Python 中,是

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

当一个数字是完全平方数时能被识别吗?具体来说,当我使用

时我是否应该担心
int(n**0.5)  # instead of
int(n**0.5 + 0.000000001)

由于精度误差,我可能会意外地得到比实际平方根小一的数字?

python math square-root
7个回答
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。


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
的数字,只要您检查精度(可配置),它就会抛出错误而不是错误的答案...


3
投票

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

当输入值是完全平方数时,这些计算是否能够识别?

不,他们没有。浮点算术没有完全平方的概念。

对于数字具有比浮点尾数中可用数字更多的有效数字的值,大整数可能无法表示。因此很容易看出,对于不可表示的输入值,

n**0.5
可能不准确。而且您建议通过添加一个小值来修复通常不会解决问题。

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


1
投票

您可以在转换为 int 之前使用 round(number, important_figures) ,我不记得在进行浮点到整数转换时 python 是否截断或舍入。

无论如何,由于Python使用浮点运算,所以所有的陷阱都适用。参见:
http://docs.python.org/2/tutorial/floatingpoint.html


1
投票

完全平方值将没有小数部分,因此您主要担心的是非常大的值,对于此类值,1 或 2 的差异显着意味着您将需要一个支持如此高精度的特定数值库(正如 DSM 提到的,自 Python 2.4 以来的标准库

Decimal
库应该能够执行您想要的操作,因为它支持任意精度。

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


1
投票

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

这仅处理实际传递给

sqrt
的值。是否可以将数字毫无错误地从另一种格式转换为
sqrt
的浮点输入是一个单独的问题。


0
投票

这个问题很老了,多年来发生了很多变化。现在 python 中有一个

math.isqrt
函数,它的功能几乎与
int(math.sqrt(...))
相同,但在精度上没有松懈:

>>> int(math.sqrt(100000000000000000000000000000000000**2))
99999999999999996863366107917975552
>>> math.isqrt(100000000000000000000000000000000000**2)
100000000000000000000000000000000000
© www.soinside.com 2019 - 2024. All rights reserved.