【问题标题】:Distinguishing large integers from near integers in python在python中区分大整数和近整数
【发布时间】:2016-08-02 12:23:14
【问题描述】:

我想避免我的代码将近似整数误认为整数。例如,58106601358565889 的平方根为 241,053,109.00000001659385359763188,但是当我使用以下布尔测试时,58106601358565889 欺骗了我,让我认为它是一个完美的平方:

a = 58106601358565889
b = math.sqrt(a)
print(b == int(b))

精度不一定是问题,因为如果我重新检查,我会得到正确的(错误)结论:

print(a == b**2)

测试真整数与近似整数的更好方法是什么? math.sqrt 隐藏在我的代码中的另一个定义中,如果可能的话,我想避免插入平方根的检查。如果这不是一个好问题,我深表歉意;我是 python 新手。

【问题讨论】:

  • 应该返回true 是你想要的吗?
  • 如果我的理解是正确的,它应该返回 False
  • 第一个 print(b == int(b)) 我要假。
  • Jeptha,用十进制检查我的答案

标签: python-3.x integer long-integer floating-accuracy math.sqrt


【解决方案1】:
import numpy as np
import math
from decimal import *

a = 58106601358565889
b = np.sqrt(a)
c = math.sqrt(a)
d = Decimal(58106601358565889).sqrt()


print(d)
print(int(d))

print(c)
print(int(c))

print(b)
print(int(b))

o/p

241053109.0000000165938535976
241053109
241053109.0
241053109
241053109.0
241053109

我会说使用decimal

预期代码:

from decimal import *
d = Decimal(58106601358565889).sqrt()
print(d == int(d))

o/p

False

【讨论】:

  • Decimal 仍然会以有限的(尽管可配置的)精度进行计算。在Decimal 中进行所有数学运算只会将问题推迟到更大的输入大小,除非您执行额外的配置和辅助检查。
  • 谢谢,Decimal 成功了。我不知道那个选项。
  • 感谢 user2357112,我将不得不研究 Decimal 的精度限制。
  • @Jeptha:作为此解决方案不起作用的示例,请尝试使用 a = 10000000000000200000000000002。这不是一个正方形,但无论如何你都会得到True
  • 你说得对,user2357112,我仍然需要仔细检查那个:int(math.sqrt(a)**2) == a,它正确地为你提到的a 提供了False
【解决方案2】:

这不是区分整数和非整数的问题,因为b 确实是一个整数*。 Python 浮点数的精度不足以将a 的平方根表示为足够多的数字来获得它的任何小数部分。您进行的第二次检查:

print(a == b**2)

只打印False,因为虽然b 是一个整数,但b**2 仍然不是a

如果您想测试非常大的整数是否是精确平方,请考虑自己实现平方根算法。

*与 0 小数部分一样,而不是 isinstance(b, int)

【讨论】:

  • 感谢您指出这一点;这对我来说是一个糟糕的假设。
【解决方案3】:

问题不在于int 的精度,而是浮点数的有限精度

>>> import math
>>> math.sqrt(58106601358565889)
241053109.0
>>> math.sqrt(58106601358565889) - 241053109
0.0

我认为双重检查是显而易见的解决方案

【讨论】:

  • 那么复查真的有必要吗?
  • @Jeptha:仔细检查还不够好;它有自己的问题。例如,它在a = 100000000000000000001**2 上失败。
  • @Jeptha,任何大于该值的浮点数将始终是整数。也许你可以测试(a == b*b)
  • 小数呢?
【解决方案4】:

您还可以查看gmpy2 库。它具有计算整数平方根以及整数平方根加余数的功能。没有精度限制。

>>> import gmpy2
>>> gmpy2.isqrt(58106601358565889)
mpz(241053109)
>>> gmpy2.isqrt_rem(58106601358565889)
(mpz(241053109), mpz(8))
>>> 

免责声明:我维护gmpy2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-01
    • 2023-04-09
    • 2021-05-20
    • 2015-01-08
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多