我在Python 2.7中有一个舍入问题导致意外输出。我试图让p1和p2的组合总计达到0.6或更少。
lazy val root = (project in file(".")).
settings(
name := "TestkitAfterall",
version := "1.0",
scalaVersion := "2.11.7"
)
lazy val akkaVersion = "2.4.0"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"com.typesafe.akka" %% "akka-testkit" % akkaVersion,
"org.scalatest" % "scalatest_2.11" % "2.2.5"
)
然而,当我运行它时,它不包括p11 + p22 = 0.6的所有值:
from itertools import product
P = []
p1 = [0.0,0.2,0.4,0.6]
p2 = [0.0,0.2,0.4,0.6]
for p11,p22 in product(p1,p2):
if p11+p22 <= max(p1):
P.append((p11,p22))
设置[(0.0, 0.0),
(0.0, 0.2),
(0.0, 0.4),
(0.0, 0.6),
(0.2, 0.0),
(0.2, 0.2),
(0.4, 0.0),
(0.6, 0.0)]
时,它可以正常工作。对于不同的p11+p22 <= max(p1)+0.01
和p1
,问题可能会也可能不会发生。我发现这种行为非常奇怪,导致非常不可靠的结果。
这可能与浮动精度问题有关。在我看来,这种行为不应该存在于Python中,因为R和Matlab也没有这种行为。这有什么简单的方法吗?
答案 0 :(得分:5)
计算机具有数字的内部表示。在大多数情况下,这些表示具有固定的位数。这导致仅可表示固定数量的数字。例如,您可能知道像C这样的语言具有整数的最大值。
类似地,您不能存储某些浮点数的精确表示。由于计算机使用基数为2,因此基数10中有一些数字具有短的有限表示但二进制数字很长。有关详细信息,请参阅IEEE 754。
这里没有什么可以解决的,因为一切都像指定的那样工作。但你必须知道这些类型的问题。当你意识到存在问题的事实时,有两种策略可以解决它。
使用 epsilons ( - &gt;不要与确切数字进行比较,但要检查数字是否在数字周围的非常小的间隔内。此间隔的长度通常称为&#34; epsilon&#34;)或使用任意精确表示(见fractions
。第二种只有当你可以影响数字如何被放入程序时才有效,例如
from itertools import product
from fractions import Fraction
P = []
p1 = [Fraction(0.0), Fraction(2, 10), Fraction(4, 10), Fraction(6, 10)]
p2 = [Fraction(0.0), Fraction(2, 10), Fraction(4, 10), Fraction(6, 10)]
for p11, p22 in product(p1, p2):
if p11+p22 <= max(p1):
P.append((p11, p22))
答案 1 :(得分:1)
因为固定位宽浮点上的limitations,您需要使用任意精度浮点包或明确地与+/- epsilon量进行比较。
Python包含decimal(对于'算法,其工作方式与人们在学校学习的算法相同'):
from itertools import product
import decimal
P = []
p1 = map(decimal.Decimal, ['0.0','0.2','0.4','0.6'])
p2 = map(decimal.Decimal, ['0.0','0.2','0.4','0.6'])
for p11,p22 in product(p1,p2):
if p11+p22 <= max(p1):
P.append((p11,p22))
答案 2 :(得分:1)
如果您想与matlab或R进行比较,或者遇到性能问题,这里有一个简单的方法,np.isclose()
作为解决方法。
p1 = [0.0,0.2,0.4,0.6]
p2 = [0.0,0.2,0.4,0.6]
sums=np.add.outer(p1,p2)
P1,P2=np.meshgrid(p1,p2)
compare = (sums<0.6) | np.isclose(sums,0.6)
print(np.dstack((P1,P2))[compare])
给出:
[[ 0. 0. ]
[ 0.2 0. ]
[ 0.4 0. ]
[ 0.6 0. ]
[ 0. 0.2]
[ 0.2 0.2]
[ 0.4 0.2]
[ 0. 0.4]
[ 0.2 0.4]
[ 0. 0.6]]
答案 3 :(得分:-1)
一种方法是定义一个不同的不等式比较函数,
for p11,p22 in product(p1,p2):
if less_or_nearly_equal(p11+p22,max(p1)):
P.append((p11,p22))
并在比较中使用\而不是&lt; =
{{1}}
(我希望我的语法在函数定义中是正确的。)