Python:如何保持sqrt()的平方精度?

时间:2017-02-09 23:49:37

标签: python

我认为这是一个很受欢迎的问题,但我找不到答案:

当一个整数的平方根被平方时,我希望结果是一个整数,但我得到以下结果:

from math import sqrt
from decimal import Decimal 

a = 5
b = sqrt(Decimal(a))
c = 2 * b ** 2
print(a, c)
if c.is_integer():
    print('c is integer')
    do something ...
else:
    print('c is NOT integer')

结果:

5 10.000000000000002
c is NOT integer

我也试过没有decimal.Decimal()但它也没有用。 解决这个问题的最佳方法是什么? 上面的代码针对这个问题进行了简化,但如果可能的话我想要一个通用的解决方案我使用的是Python 3.5。

2 个答案:

答案 0 :(得分:4)

如果你想要一个准确的'代表sqrt(5)你必须熟悉CAS或计算机代数系统,例如sympy。

>>> import sympy
>>> s = sympy.sqrt(5)
>>> s
sqrt(5)
>>> s*s
5
>>> type(s*s)
<class 'sympy.core.numbers.Integer'>
>>> float(s)
2.23606797749979

sqrt(5)是一个所谓的无理数。这意味着它不能写成一个分数。使用正常的算术计算机只能存储分数而不是所有这些,所以在这条路上你运气不好。

以下是您的代表片段的翻译,演示了simplify的功能:

import sympy

def check_int(x, name='input'):
    print('ah', name, '=', x)
    sx = sympy.simplify(x)
    if sx != x:
        print('let me think...')
        print("that's", sx)
    if isinstance(sx, (int, sympy.Integer)):
        print(name, 'is integer')
    else:
        print(name, 'is NOT integer')
    print()

s = sympy.sqrt(5)
t = sympy.sqrt(3)
check_int(5)
check_int(s)
check_int(s**2)
check_int((s+1)**2)
check_int((s+1)**2-2*s)
check_int((s-t)**2)

输出:

ah input = 5
input is integer

ah input = sqrt(5)
input is NOT integer

ah input = 5
input is integer

ah input = (1 + sqrt(5))**2
input is NOT integer

ah input = -2*sqrt(5) + (1 + sqrt(5))**2
let me think...
that's 6
input is integer

ah input = (-sqrt(3) + sqrt(5))**2
let me think...
that's -2*sqrt(15) + 8
input is NOT integer

答案 1 :(得分:1)

您应该熟悉实数是多少stored in computers。长话短说,他们要么a finite precision(你只是处理它),要么你需要做symbolic calculations(这在日常软件中没有使用,但仍有其局限性。)

如果在您的特定问题域中,确实需要一个准确的平方根(以及后面的平方根的准确平方),您可能会创建自己的类型SquareRoot并重载必要的运算符。请注意,这不适用于整个数学,例如三度(x ^(1/3))的根或其他任何东西。