2017-08-08 108 views
2

标题有点误导,因为它不完全是x和x,它是x和0.3;然而,值应该是相同的。为什么x <= x false?

我:

arr = np.arange(0, 1.1, 0.1) 

,我得到:

arr[arr <= 0.3] 
> array([0., 0.1, 0.2]) 

正确的结果应该是:

arr[arr <= 0.3] 
> array([0., 0.1, 0.2, 0.3]) 

我还没有偶然发现了这个问题。我知道它与浮点精度有关......但我能在这里做什么?

+0

嗯......'改编[编曲。 round(1)<= 0.3]'... –

+0

所以我应该在执行任何比较之前总是*整数? – Xiphias

+1

花车之间的等价性总是有风险的事情来测试。 –

回答

4

不要依靠比较花车的平等(除非你知道正好你正在处理的花车)。 既然你知道用来生成阵列是0.1步长,

arr = np.arange(0, 1.1, 0.1) 

,你可以提高阈值,0.3的,由半数步长找到了新的阈值,且在arr值之间的安全:

In [48]: stepsize = 0.1; arr[arr < 0.3+(stepsize/2)] 
Out[48]: array([ 0. , 0.1, 0.2, 0.3]) 

顺便说一句,在np.arange(0, 1.1, 0.1)1.1是同样的想法的一个应用 - 定的浮点运算的变幻莫测,我们也不能肯定这1.0将是如果我们写了np.arange(0, 1.0, 0.1),那么这个结果就会增加,所以右边的终点增加了stepize。


从根本上说,这个问题归结为floating-point arithmetic being inaccurate

In [17]: 0.1+0.2 == 0.3 
Out[17]: False 

所以在阵列中的第四值大于0.3一点点。

In [40]: arr = np.arange(0,1.1, 0.1) 
In [41]: arr[3] 
Out[41]: 0.30000000000000004 

注意,舍入可能不是一个可行的解决方案。例如, 如果arr具有D型细胞float128

In [53]: arr = np.arange(0, 1.1, 0.1, dtype='float128') 

In [56]: arr[arr.round(1) <= 0.3] 
Out[56]: array([ 0.0, 0.1, 0.2], dtype=float128) 

虽然使float128制成arr[3]接近小数0.3 D型,

In [54]: arr[3] 
Out[54]: 0.30000000000000001665 

现在四舍五入不会产生数小于0.3:

In [55]: arr.round(1)[3] 
Out[55]: 0.30000000000000000001 
+1

即使你不知道步长,你*仍然可以做类似'arr [arr <= 0.3 + sys.float_info.epsilon] - 但是,我并不完全相信它会*总是*足以保证比较工作...你有什么想法? –

+0

虽然 - 上面似乎也适用于你的'float128'范例... –

+0

我不确定如何量化'np.arange(...)'中的值可能离他们多远理想化的小数对应。根据浮点数,连续浮点数之间的差距会发生变化,并且可能会大于'sys.float_info.epsilon'。例如, 'x = 10.3; (np.nextafter(x,np.inf) - x)> sys.float_info.epsilon'。 – unutbu

1

Unutbu指出了主要问题。您应该避免比较浮点数,因为它们有四舍五入的错误。

然而,这是一个很多人遇到的问题,因此有一个函数可以帮助你解决这个问题; np.isclose你的情况,这将导致:

arr[np.logical_or(arr <= 0.3, np.isclose(0.3, arr))] 
>>> array([0., 0.1, 0.2, 0.3]) 

在这种情况下,这可能不是最好的选择,但它可能有助于了解该功能。

旁注: 如果没有人向你解释过,为什么会发生这种情况。基本上,计算机将所有内容保存为二进制文件,但0.1是二进制的周期数,这意味着计算机无法保存所有数字(因为数量无限多)。十进制等效是:

1/3 + 1/3 + 1/3 = 0.33333 0.33333 + 0.33333 + = 0.99999

这是不是1

相关问题